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

Data Structures

struct  KSEPI_SEQUENCE
 
struct  KSEPI_FLEET_SEQUENCE
 

Macros

#define KSEPI_MINHNOVER   8 /* N.B. overscans below about 16-24 should be avoided for long TE */
 
#define KSEPI_MAXRBW_NORAMPSAMPLING   125.0
 
#define KSEPI_DEFAULT_SSI_TIME_ICEHARDWARE   100
 
#define KSEPI_DEFAULT_SSI_TIME   1500
 
#define KSEPI_INIT_SEQUENCE1   KS_INIT_SEQ_CONTROL, KS_INIT_EPI, KS_INIT_EPI, KS_INIT_TRAP, KS_INIT_SELRF, KS_INIT_SELRF, KS_INIT_SELRF, KS_INIT_TRAP, KS_INIT_TRAP, KS_INIT_WAIT, KS_INIT_WAIT
 
#define KSEPI_INIT_SEQUENCE2   KS_INIT_TRAP, KS_INIT_TRAP, KS_INIT_PHASEENCODING_PLAN, KS_INIT_PHASEENCODING_PLAN, KS_INIT_PHASEENCODING_PLAN, NULL
 
#define KSEPI_INIT_SEQUENCE   {KSEPI_INIT_SEQUENCE1, KSEPI_INIT_SEQUENCE2};
 
#define KSEPI_FLEET_INIT_SEQUENCE   {KS_INIT_SEQ_CONTROL, KS_INIT_EPI, KS_INIT_TRAP, KS_INIT_SELRF, KS_INIT_WAIT, KS_INIT_WAIT, KS_INIT_PHASEENCODING_PLAN};
 
#define MAX_DIFSCHEME_LENGTH   1024
 

Typedefs

typedef float DIFFSCHEME[3][MAX_DIFSCHEME_LENGTH]
 

Enumerations

enum  KSEPI_MULTISHOT_MODE { KSEPI_MULTISHOT_OFF, KSEPI_MULTISHOT_ALLVOLS, KSEPI_MULTISHOT_1STVOL, KSEPI_MULTISHOT_B0VOLS }
 
enum  OFFLINE_DIFFRETURN_MODE {
  OFFLINE_DIFFRETURN_ALL = 0, OFFLINE_DIFFRETURN_ACQUIRED = 1, OFFLINE_DIFFRETURN_B0 = 2, OFFLINE_DIFFRETURN_MEANDWI = 4,
  OFFLINE_DIFFRETURN_MEANADC = 8, OFFLINE_DIFFRETURN_EXPATT = 16, OFFLINE_DIFFRETURN_FA = 32, OFFLINE_DIFFRETURN_CFA = 64
}
 

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 ("EPI [KSFoundation]")
 
 psdname ("ksepi")
 
STATUS ksepi_eval_flowcomp_phase (KS_TRAP *fcphase, const KS_EPI *epi, const char *desc)
 
STATUS ksepi_pg (int start_time)
 
int ksepi_scan_coreslice (const SCAN_INFO *slice_pos, int dabslice, int shot)
 
int ksepi_scan_coreslice_nargs (const SCAN_INFO *slice_pos, int dabslice, int nargs, void **args)
 
int ksepi_scan_sliceloop (int slperpass, int volindx, int passindx, int shot)
 
int ksepi_scan_sliceloop_nargs (int slperpass, int nargs, void **args)
 
STATUS ksepi_scan_seqstate (SCAN_INFO slice_info, int shot)
 
float ksepi_scan_acqloop (int passindx, int volindx, int multishotflag)
 
float ksepi_scan_scanloop ()
 
void ksepi_init_imagingoptions (void)
 
STATUS ksepi_init_UI (void)
 
STATUS ksepi_eval_UI ()
 
STATUS ksepi_eval_setuprf_3dexc (KS_SELRF *selrfexc, int rf3Dopt)
 
STATUS ksepi_eval_setuprf ()
 
STATUS ksepi_eval_setupfleet ()
 
STATUS ksepi_eval_setupobjects ()
 
STATUS ksepi_eval_TErange ()
 
STATUS ksepi_eval_inversion (KS_SEQ_COLLECTION *seqcollection)
 
STATUS ksepi_eval_tr (KS_SEQ_COLLECTION *seqcollection)
 
int ksepi_eval_ssitime ()
 
STATUS ksepi_eval_scantime ()
 
STATUS ksepi_check ()
 
STATUS ksepi_predownload_plot (KS_SEQ_COLLECTION *seqcollection)
 
STATUS ksepi_predownload_setrecon ()
 
STATUS ksepi_pg_fleet (int start_time)
 
STATUS ksepi_fleet_scan_seqstate (const SCAN_INFO *slice_info, int shot)
 
void ksepi_scan_rf_off ()
 
int ksepi_fleet_scan_coreslice (const SCAN_INFO *slice_pos, int dabslice, int shot)
 
int ksepi_fleet_scan_sliceloop (int slperpass, int volindx, int passindx)
 
STATUS ksepi_scan_init (void)
 
STATUS ksepi_scan_prescanloop (int nloops, int dda)
 
STATUS ksepi_diffusion_readtensorfile (DIFFSCHEME diffscheme, int nb0, int ndirs)
 
float ksepi_diffusion_getmaxb ()
 
void ksepi_diffusion_set_heat_scaling (DIFFSCHEME diffscheme)
 
STATUS ksepi_diffusion_init_UI ()
 
STATUS ksepi_diffusion_eval_UI ()
 
void SolveCubic (double a, double b, double c, double d, int *nsol, double *x)
 
STATUS ksepi_diffusion_calcTE (double *TE_s, int exciso2end, int crsh1_half180, int half180_crsh2, int crsh3_half180, int half180_crsh4, int readout2echo, int ramptime, float G, int bval_desired, int dualspinechoflag)
 
STATUS ksepi_diffusion_eval_gradients_TE (KSEPI_SEQUENCE *ksepi)
 
STATUS ksepi_diffusion_predownload_setrecon ()
 
STATUS ksepi_diffusion_pg (KSEPI_SEQUENCE *ksepi, int TE)
 
void ksepi_diffusion_scan_diffamp (KSEPI_SEQUENCE *ksepi, int volindx)
 

Variables

KS_SEQ_COLLECTION seqcollection
 
float ksepi_excthickness = 0
 
float ksepi_gscalerfexc = 0.9 with {0.1, 3.0, 0.9, VIS, "Excitation slice thk scaling (< 1.0 thicker slice)",}
 
int ksepi_slicecheck = 0 with {0, 1, 0, VIS, "move readout to z axis for slice thickness test",}
 
float ksepi_spoilerarea = 3000.0 with {0.0, 10000.0, 3000.0, VIS, "ksepi ksepi.spoiler gradient area",}
 
int ksepi_rfspoiling = 1 with {0, 1, 1, VIS, "Enable RF spoiling 1:on 0:off",}
 
int ksepi_fse90 = 0 with {0, 1, 0, VIS, "Use FSE90 instead of SPSP for non-fatsat",}
 
int ksepi_rf3Dopt = 0 with {0, 10, 0, VIS, "Choose optimized SPSP pulse for 3D [0:OFF]",}
 
float ksepi_kissoff_factor = 0.04 with {0, 1, 0.04, VIS, "Slice oversampling fraction on each side (3D)",}
 
float ksepi_crusherscale = 1.0 with { -20.0, 20.0, 1.0, VIS, "scaling of crusher gradient area",}
 
float ksepi_gscalerfref = 0.9 with {0.1, 3.0, 0.9, VIS, "Refocusing slice thk scaling (< 1.0 thicker slice)",}
 
int ksepi_rampsampling = 1 with {0, 1, 1, VIS, "Rampsampling [0:OFF 1:ON]",}
 
int ksepi_readlobegap = 0 with {0, 10ms, 0, VIS, "extra gap between readout lobes [us]",}
 
int ksepi_echogap = 0 with {0, 100ms, 0, VIS, "extra gap between EPI echoes [us]",}
 
int ksepi_readsign = 1 with { -1, 1, 1, VIS, "Readout polarity: +1/-1",}
 
float ksepi_readampmax = 3.0 with {0.0, 5.0, 3.0, VIS, "Max grad amp for EPI readout lobes",}
 
float ksepi_sr = 0.01 with {0.0, , 0.01, VIS, "EPI SR: amp/ramp [(G/cm) / us]",}
 
int ksepi_esp = 0 with {0, 1000000, 0, VIS, "View-only: Echo spacing in [us]",}
 
int ksepi_blipsign = KS_EPI_POSBLIPS with {KS_EPI_NEGBLIPS, KS_EPI_POSBLIPS, KS_EPI_POSBLIPS, VIS, "Blip polarity: +1/-1",}
 
int ksepi_echotime_shifting = 1 with {0, 1, 1, VIS, "Enable echo time shifting for multi shot",}
 
int ksepi_kynover = 24 with {KSEPI_MINHNOVER, 512, 24, VIS, "#extralines for MinTE",}
 
int ksepi_kznover = 0 with {0, 512, 0, VIS, "#extralines in kz",}
 
int ksepi_ky_R = 1 with {1, 512, 1, VIS, "Acceleration in ky",}
 
int ksepi_kz_R = 1 with {1, 512, 1, VIS, "Acceleration in kz",}
 
int ksepi_kz_nacslines = 16 with {0, 512, 16, VIS, "Number of acs lines in kz",}
 
int ksepi_caipi = 0 with {0, 512, 0, VIS, "CAIPIRINHA shift (affects 3D epi only. Set 0 for no CAIPI)",}
 
int ksepi_fcy = 1 with {0, 1, 0, VIS, "Flowcomp Y when opfcomp"}
 
int ksepi_fcz = 1 with {0, 1, 0, VIS, "Flowcomp Z when opfcomp"}
 
int ksepi_fleet = 0 with {0, 1, 0, VIS, "FLEET calibration volume [0:OFF 1:ON]",}
 
float ksepi_fleet_flip = 15.0 with {0.1, 90.0, 15.0, VIS, "FLEET flip angle [deg]",}
 
int ksepi_fleet_dda = 0 with {0, 200, 0, VIS, "Dummies for FLEET module",}
 
int ksepi_fleet_num_ky = 36 with {1, 512, 36, VIS, "Number of ky encodes for FLEET module",}
 
int ksepi_fleet_num_kz = 24 with {1, 512, 24, VIS, "Number of kz encodes for FLEET module (3D only)",}
 
int ksepi_reflines = 0 with {0, 96, 0, VIS, "Number of phase reference lines per shot",}
 
int ksepi_swi_returnmode = 0 with {0, 7, 0, VIS, "SWI recon 0:Off 1:Acq 2:SWI 4:SWIphase",}
 
int ksepi_pos_start = KS_RFSSP_PRETIME with {0, , KS_RFSSP_PRETIME, INVIS, "us from start until the first waveform begins",}
 
int ksepi_ssi_time = KSEPI_DEFAULT_SSI_TIME with {32, , KSEPI_DEFAULT_SSI_TIME, VIS, "time from eos to ssi in intern trig",}
 
int ksepi_dda = 1 with {0, 200, 1, VIS, "Number of dummy scans for steady state",}
 
int ksepi_debug = 1 with {0, 100, 1, VIS, "Write out e.g. plot files (unless scan on HW)"}
 
int ksepi_imsize = KS_IMSIZE_POW2 with {KS_IMSIZE_NATIVE, KS_IMSIZE_MIN256, KS_IMSIZE_POW2, VIS, "img. upsamp. [0:native 1:pow2 2:min256]"}
 
int ksepi_abort_on_kserror = FALSE with {0, 1, 0, VIS, "Hard program abort on ks_error [0:OFF 1:ON]",}
 
int ksepi_ghostcorr = 1 with {0, 1, 1, VIS, "Ghost correction [0:OFF 1:ON]",}
 
int ksepi_ref_nsegments = 1 with {1, 512, 1, VIS, "Number of kz segments in reference volume",}
 
int ksepi_multishot_control = KSEPI_MULTISHOT_B0VOLS with {KSEPI_MULTISHOT_OFF, KSEPI_MULTISHOT_B0VOLS, KSEPI_MULTISHOT_B0VOLS, VIS, "0:PI 1:All MulShot 2:1stMulShot 3:b0MulShot",}
 
float ksepi_epiqfact = 1.0 with {1.0, 10.0, 1.0, VIS, "Quetness factor for the EPI readout only",}
 
KSEPI_SEQUENCE ksepi = KSEPI_INIT_SEQUENCE
 
KSEPI_FLEET_SEQUENCE ksepi_fleetseq = KSEPI_FLEET_INIT_SEQUENCE
 
int ksepi_interechotime = 0
 
float ksepi_echotime_shifting_shotdelay = 0
 
int ksepi_echotime_shifting_sumdelay = 0
 
int sequence_iopts []
 
int rfspoiling_phase_counter = 0
 
int ksepi_diffusion_ramptime = 1500 with {300, 30ms, 1500, VIS, "Ramp times for diffusion gradients", }
 
float ksepi_diffusion_maxamp = 0.0 with {0.0, 7.0, 3.0, VIS, "Cap for diffusion gradient amplitude", }
 
float ksepi_diffusion_amp = 0.0 with {0.0, 7.0, 0.0, VIS, "View-only: Current diffusion gradient amplitude", }
 
int ksepi_diffusion_heat_avg = 1 with {0, 1, 1, VIS, "Root mean sqared averaging diffusion amplitudes heat calculations", }
 
float ksepi_diffusion_scaleX_heatcal = 1 with {0, 1, 1, VIS, "View-only: x diffusion gradient amplitude for heating calculations", }
 
float ksepi_diffusion_scaleY_heatcal = 1 with {0, 1, 1, VIS, "View-only: y diffusion gradient amplitude for heating calculations", }
 
float ksepi_diffusion_scaleZ_heatcal = 1 with {0, 1, 1, VIS, "View-only: z diffusion gradient amplitude for heating calculations", }
 
int ksepi_diffusion_echotime = 0 with {0, , 0, VIS, "View-only: Echo time necessary to meet the desired b-value", }
 
float ksepi_diffusion_2ndcrushfact = 2.0 with {0.1, 10.0, 2.0, VIS, "Scale factor for 2nd crusher for opdualspinecho",}
 
int ksepi_diffusion_returnmode = OFFLINE_DIFFRETURN_ALL with {OFFLINE_DIFFRETURN_ALL, 128, OFFLINE_DIFFRETURN_ALL, VIS, "Diff maps All:0 Acq:1 b0:2 DWI:4 ADC:8 Exp:16 FA:32 cFA:64",}
 
DIFFSCHEME diffscheme
 
int ndiffdirs = 6
 

Detailed Description

MR-contrasts supported

Features

Macro Definition Documentation

◆ KSEPI_MINHNOVER

#define KSEPI_MINHNOVER   8 /* N.B. overscans below about 16-24 should be avoided for long TE */

◆ KSEPI_MAXRBW_NORAMPSAMPLING

#define KSEPI_MAXRBW_NORAMPSAMPLING   125.0

◆ KSEPI_DEFAULT_SSI_TIME_ICEHARDWARE

#define KSEPI_DEFAULT_SSI_TIME_ICEHARDWARE   100

◆ KSEPI_DEFAULT_SSI_TIME

#define KSEPI_DEFAULT_SSI_TIME   1500

◆ KSEPI_INIT_SEQUENCE1

◆ KSEPI_INIT_SEQUENCE2

◆ KSEPI_INIT_SEQUENCE

#define KSEPI_INIT_SEQUENCE   {KSEPI_INIT_SEQUENCE1, KSEPI_INIT_SEQUENCE2};

◆ KSEPI_FLEET_INIT_SEQUENCE

◆ MAX_DIFSCHEME_LENGTH

#define MAX_DIFSCHEME_LENGTH   1024

Typedef Documentation

◆ DIFFSCHEME

typedef float DIFFSCHEME[3][MAX_DIFSCHEME_LENGTH]

Enumeration Type Documentation

◆ KSEPI_MULTISHOT_MODE

Enums to switch between multishot vs. parallel imaging modes

Enumerator
KSEPI_MULTISHOT_OFF 
KSEPI_MULTISHOT_ALLVOLS 
KSEPI_MULTISHOT_1STVOL 
KSEPI_MULTISHOT_B0VOLS 
88  {
89  KSEPI_MULTISHOT_OFF, /* 0 */
91  KSEPI_MULTISHOT_1STVOL, /* 2 */
92  KSEPI_MULTISHOT_B0VOLS, /* 3 */
Definition: ksepi_implementation.e:91
Definition: ksepi_implementation.e:89
Definition: ksepi_implementation.e:90
Definition: ksepi_implementation.e:92
KSEPI_MULTISHOT_MODE
Enums to switch between multishot vs. parallel imaging modes
Definition: ksepi_implementation.e:88

◆ OFFLINE_DIFFRETURN_MODE

Enumerator
OFFLINE_DIFFRETURN_ALL 
OFFLINE_DIFFRETURN_ACQUIRED 
OFFLINE_DIFFRETURN_B0 
OFFLINE_DIFFRETURN_MEANDWI 
OFFLINE_DIFFRETURN_MEANADC 
OFFLINE_DIFFRETURN_EXPATT 
OFFLINE_DIFFRETURN_FA 
OFFLINE_DIFFRETURN_CFA 
39  {
Definition: ksepi_implementation_diffusion.e:46
Definition: ksepi_implementation_diffusion.e:40
Definition: ksepi_implementation_diffusion.e:44
Definition: ksepi_implementation_diffusion.e:41
Definition: ksepi_implementation_diffusion.e:43
Definition: ksepi_implementation_diffusion.e:42
Definition: ksepi_implementation_diffusion.e:45
OFFLINE_DIFFRETURN_MODE
Definition: ksepi_implementation_diffusion.e:39
Definition: ksepi_implementation_diffusion.e:47

Function Documentation

◆ cvinit()

STATUS cvinit ( void  )
86  {
87  STATUS status;
88 
89  obl_method = PSD_OBL_OPTIMAL;
90 
91  status = GEReq_cvinit();
92  if (status != SUCCESS) return status;
93 
94  /* reset debug file ./ks_debug.txt (SIM) or /usr/g/mrraw/ks_debug.txt (HW) */
95  ks_dbg_reset();
96 
97  /* Imaging Options buttons */
99 
100  /* Setup UI buttons */
101  status = ksepi_init_UI();
102  if (status != SUCCESS) return status;
103 
104  return SUCCESS;
105 
106 } /* cvinit() */
int obl_method
Definition: GERequired.e:234
void ksepi_init_imagingoptions(void)
Initial handling of imaging options buttons and top-level CVs at the PSD type-in page
Definition: ksepi_implementation.e:279
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
STATUS ksepi_init_UI(void)
Initial setup of user interface (UI) with default values for menus and fields
Definition: ksepi_implementation.e:368

◆ cveval()

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

◆ my_cveval()

STATUS my_cveval ( void  )
125  {
126  STATUS status;
127 
129 
130  status = GEReq_cveval();
131  if (status != SUCCESS) return status;
132 
133  /* User Interface updates & opuserCV sync */
134  status = ksepi_eval_UI();
135  if (status != SUCCESS) return status;
136 
137  /* Setup sequence objects */
138  status = ksepi_eval_setupobjects();
139  if (status != SUCCESS) return status;
140 
141  /* Calculate minimum (and maximum TE) */
142  status = ksepi_eval_TErange();
143  if (status != SUCCESS) return status;
144 
145  /* Run the sequence once (and only once after ksepi_eval_setupobjects()) in cveval() to
146  get the sequence duration and the number of object instances (for grad/rf limits in GEReq...limits()) */
147  status = ksepi_pg(ksepi_pos_start);
148  if (status != SUCCESS) return status;
149 
151  if (status != SUCCESS) return status;
152 
153  if (ksepi_fleet) {
155  if (status != SUCCESS) return status;
156 
158  if (status != SUCCESS) return status;
159  }
160 
161  /*--------- Begin: Additional sequence modules -----------*/
162 
163 
164  /* Spatial Sat */
165  status = ksspsat_eval(&seqcollection);
166  if (status != SUCCESS) return status;
167 
168  /* ChemSat */
169  status = kschemsat_eval(&seqcollection);
170  if (status != SUCCESS) return status;
171 
172  /* Inversion (general & EPI specific). Must be the last sequence module added */
174  if (status != SUCCESS) return status;
175 
176 
177  /*--------- End: Additional sequence modules -----------*/
178 
179 
180  /* Min TR, #slices per TR, RF/gradient heating & SAR */
181  status = ksepi_eval_tr(&seqcollection);
182  if (status != SUCCESS) return status;
183 
184  /* RF scaling across sequence modules */
186  if (status != SUCCESS) return status;
187 
188  /* scan time */
189  status = ksepi_eval_scantime();
190  if (status != SUCCESS) return status;
191 
192  return SUCCESS;
193 
194 } /* my_cveval() */
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:76
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 kschemsat_eval(KS_SEQ_COLLECTION *seqcollection)
Chemsat evaluation function, to be called from the cveval() function of the main sequence
Definition: KSChemSat.e:273
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:201
STATUS ksepi_eval_TErange()
Sets the min/max TE based on the durations of the sequence objects in KSEPI_SEQUENCE (ksepi)...
Definition: ksepi_implementation.e:1355
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 ksepi_eval_UI()
Gets the current UI and checks for valid inputs
Definition: ksepi_implementation.e:829
STATUS ksepi_pg(int)
The ksepi (main) pulse sequence
Definition: ksepi_implementation.e:1958
STATUS ksepi_eval_tr(KS_SEQ_COLLECTION *seqcollection)
Evaluation of number of slices / TR, set up of slice plan, TR validation and SAR checks
Definition: ksepi_implementation.e:1622
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:49
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
STATUS ksepi_eval_inversion(KS_SEQ_COLLECTION *seqcollection)
Wrapper function to KSInversion functions to add single and dual IR support to this sequence...
Definition: ksepi_implementation.e:1536
int ksepi_pos_start
Definition: ksepi_implementation.e:172
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:80
STATUS ksepi_pg_fleet(int start_time)
The fleet pulse sequence for GRAPPA calibration
Definition: ksepi_implementation.e:2201
STATUS ksepi_eval_scantime()
Set the number of dummy scans for the sequence and calls ksepi_scan_scanloop() to determinethe length...
Definition: ksepi_implementation.e:1722
int ksepi_fleet
Definition: ksepi_implementation.e:153
STATUS ksepi_eval_setupobjects()
Sets up all sequence objects for the main sequence module (KSEPI_SEQUENCE ksepi)
Definition: ksepi_implementation.e:1182
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  )
201  {
202  STATUS status;
203 
204  status = my_cveval();
205  if (status != SUCCESS) return status;
206 
207  status = GEReq_cvcheck();
208  if (status != SUCCESS) return status;
209 
210  status = ksepi_check();
211  if (status != SUCCESS) return status;
212 
214 
215  return SUCCESS;
216 
217 } /* cvcheck() */
int ksepi_abort_on_kserror
Definition: ksepi_implementation.e:177
STATUS GEReq_cvcheck(void)
Helper function to be called at the beginning of cvcheck()
Definition: GERequired.e:2407
STATUS ksepi_check()
Returns error of various parameter combinations that are not allowed for ksepi
Definition: ksepi_implementation.e:1759
int abort_on_kserror
Definition: KSFoundation_common.c:40
STATUS my_cveval(void)
Definition: ksepi.e:125

◆ predownload()

STATUS predownload ( void  )
228  {
229  STATUS status;
230  int numvols2store;
231 
232  status = GEReq_predownload();
233  if (status != SUCCESS) return status;
234 
235  /* Set filter slot # for SCAN, APS2, MPS2 */
239 
240  /* slice ordering */
241  /* The following GE globals must be set appropriately:
242  data_acq_order[], rsp_info[], rsprot[], rsptrigger[]. This is a must for a main pulse sequence */
243  if (opimode == PSD_2D) {
245  } else {
246  status = GEReq_predownload_store_sliceplan3D(opslquant, opvquant);
247  }
248  if (status != SUCCESS) return status;
249 
250  /* generic rh-vars setup */
251  numvols2store = ksepi_fleet + ksepi_ghostcorr + opfphases;
252  rhnecho = opnecho + (ksepi_reflines > 0);
254  if (status != SUCCESS) return status;
255 
256  /* KSInversion predownload */
257  status = ksinv_predownload_setrecon();
258  if (status != SUCCESS) return status;
259 
260  /* Diffusion predownload */
262  if (status != SUCCESS) return status;
263 
264  /* further sequence specific recon settings that have not been set correctly at this point */
265  status = ksepi_predownload_setrecon();
266  if (status != SUCCESS) return status;
267 
268  /* plotting of sequence modules and slice timing to disk */
270 
271  return SUCCESS;
272 
273 } /* predownload() */
STATUS GEReq_predownload_setrecon_epi(KS_EPI *epi, int numvols2store, const KS_SLICE_PLAN slice_plan, int echogap, int blipsign, int datadestination, int multishotflag, int staticghostcal, int imsize_policy)
Wrapper function that set up rh*** variable for a KS_EPI object using other functions
Definition: GERequired.e:2059
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
STATUS ksepi_predownload_plot(KS_SEQ_COLLECTION *seqcollection)
Plotting of sequence modules and slice timing to PNG/SVG/PDF files
Definition: ksepi_implementation.e:1838
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
KS_EPI dynreftrain
Definition: ksepi_implementation.e:51
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:201
STATUS ksepi_predownload_setrecon()
Last-resort function to override certain recon variables not set up correctly already
Definition: ksepi_implementation.e:1911
STATUS ksinv_predownload_setrecon()
Sets IR-related recon variables in predownload
Definition: KSInversion.e:1898
KS_EPI epitrain
Definition: ksepi_implementation.e:50
int duration
Definition: KSFoundation.h:1845
int ksepi_interechotime
Definition: ksepi_implementation.e:204
KS_READTRAP read
Definition: KSFoundation.h:1837
int ksepi_blipsign
Definition: ksepi_implementation.e:135
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_SEQ_COLLECTION seqcollection
Definition: ksepi.e:80
KS_SLICE_PLAN ks_slice_plan
Definition: GERequired.e:217
int ksepi_reflines
Definition: ksepi_implementation.e:162
int ksepi_ghostcorr
Definition: ksepi_implementation.e:178
KS_READ acq
Definition: KSFoundation.h:1574
STATUS GEReq_predownload(void)
Helper function to be called at the beginning of predownload()
Definition: GERequired.e:2451
int ksepi_imsize
Definition: ksepi_implementation.e:176
int ksepi_fleet
Definition: ksepi_implementation.e:153
int ksepi_multishot_control
Definition: ksepi_implementation.e:180
STATUS ksepi_diffusion_predownload_setrecon()
Definition: ksepi_implementation_diffusion.e:729
KS_EPI epitrain
Definition: ksepi_implementation.e:77

◆ pulsegen()

STATUS pulsegen ( void  )
281  {
282 
284 
285  /* Main Pulse Sequence */
287  KS_SEQLENGTH(seqcore, ksepi.seqctrl);
288 
289  /* Spatial Sat */
291 
292  /* ChemSat sequence module */
294  KS_SEQLENGTH(seqKSChemSat, kschemsat.seqctrl); /* does nothing if kschemsat.seqctrl.duration = 0 */
295 
296  /* Inversion sequence modules */
297  ksinv_pulsegen();
298 
299  /* FLEET module */
302 
304 
305  buildinstr(); /* load the sequencer memory */
306 
307 
308  return SUCCESS;
309 
310 } /* pulsegen() */
KSCHEMSAT_SEQUENCE kschemsat
Definition: KSChemSat.e:89
int kschemsat_pg(KSCHEMSAT_SEQUENCE *chemsat)
The kschemsat (fatsat) pulse sequence module
Definition: KSChemSat.e:320
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:76
KS_SEQLENGTH(seq_name, seq_struct)
Creates a hardware sequence for the current sequence module
Definition: GERequired.e:65
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:201
STATUS ksepi_pg(int)
The ksepi (main) pulse sequence
Definition: ksepi_implementation.e:1958
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: ksepi_implementation.e:49
int ksepi_pos_start
Definition: ksepi_implementation.e:172
STATUS ksspsat_pulsegen()
Definition: KSSpSat.e:754
KS_SEQ_CONTROL seqctrl
Definition: KSChemSat.e:71
STATUS ksepi_pg_fleet(int start_time)
The fleet pulse sequence for GRAPPA calibration
Definition: ksepi_implementation.e:2201
void GEReq_pulsegenBegin(void)
Helper function to be called at the beginning of pulsegen()
Definition: GERequired.e:2527

◆ mps2()

STATUS mps2 ( void  )
330  {
331 
332  rspent = L_MPS2;
333  strcpy(psdexitarg.text_arg, "mps2");
334 
335  if (ksepi_scan_init() == FAILURE)
336  return rspexit();
337 
338  if (ksepi_scan_prescanloop(30000, ksepi_dda) == FAILURE)
339  return rspexit();
340 
341  rspexit();
342 
343  return SUCCESS;
344 
345 } /* mps2() */
STATUS ksepi_scan_init(void)
Common initialization for prescan entry points MPS2 and APS2 as well as the SCAN entry point...
Definition: ksepi_implementation.e:2912
int ksepi_dda
Definition: ksepi_implementation.e:174
STATUS ksepi_scan_prescanloop(int nloops, int dda)
Prescan loop called from both APS2 and MPS2 entry points
Definition: ksepi_implementation.e:2940
int rspent
Definition: GERequired.e:2626
PSD_EXIT_ARG psdexitarg

◆ aps2()

STATUS aps2 ( void  )
353  {
354 
355  rspent = L_APS2;
356  strcpy(psdexitarg.text_arg, "aps2");
357 
358  if (ksepi_scan_init() == FAILURE)
359  return rspexit();
360 
361  if (ksepi_scan_prescanloop(100, ksepi_dda) == FAILURE)
362  return rspexit();
363 
364  rspexit();
365 
366  return SUCCESS;
367 
368 } /* aps2() */
STATUS ksepi_scan_init(void)
Common initialization for prescan entry points MPS2 and APS2 as well as the SCAN entry point...
Definition: ksepi_implementation.e:2912
int ksepi_dda
Definition: ksepi_implementation.e:174
STATUS ksepi_scan_prescanloop(int nloops, int dda)
Prescan loop called from both APS2 and MPS2 entry points
Definition: ksepi_implementation.e:2940
int rspent
Definition: GERequired.e:2626
PSD_EXIT_ARG psdexitarg

◆ scan()

STATUS scan ( void  )
377  {
378 
379  rspent = L_SCAN;
380  strcpy(psdexitarg.text_arg, "scan");
381 
382  if (ksepi_scan_init() == FAILURE)
383  return rspexit();
384 
385  /* Scan hierarchy:
386 
387  Without inversion:
388  ksepi_scan_scanloop() - Data for the entire scan
389  ksepi_scan_acqloop() - All data for one set of slices that fit within one TR (one acquisition)
390  ksepi_scan_sliceloop() - One set of slices that fit within one TR played out for one shot
391  ksepi_scan_coreslice() - One slice playout, with optional other sequence modules
392 
393  With inversion:
394  ksepi_scan_scanloop() - Data for the entire scan
395  ksepi_scan_acqloop() - All data for one set of slices that fit within one TR (one acquisition)
396  ksinv_scan_sliceloop() - One set of slices that fit within one TR played out for one shot
397  using the sliceloop in KSInversion.e. Note that ksinv_scan_sliceloop()
398  takes over the TR timing from ksepi_scan_sliceloop() and uses a
399  function pointer to ksepi_scan_coreslice_nargs() to execute the
400  contents of ksepi_scan_coreslice().
401  */
403 
405 
406  /* So we can see the sequence in plotter after scan completes */
408 
409  rspexit();
410 
411  return SUCCESS;
412 
413 } /* scan() */
STATUS ksepi_scan_init(void)
Common initialization for prescan entry points MPS2 and APS2 as well as the SCAN entry point...
Definition: ksepi_implementation.e:2912
void ks_scan_switch_to_sequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1356
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
float ksepi_scan_scanloop()
Plays out all volumes and passes of a single or multi-pass scan
Definition: ksepi_implementation.e:2850
int GEReq_endofpassandscan()
Sets SSP word in sequence off_GEpass() to tell system that scan is done
Definition: GERequired.e:2606
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:49
int rspent
Definition: GERequired.e:2626
PSD_EXIT_ARG psdexitarg

◆ abstract()

abstract ( "EPI "  [KSFoundation])

◆ psdname()

psdname ( "ksepi"  )

◆ ksepi_eval_flowcomp_phase()

STATUS ksepi_eval_flowcomp_phase ( KS_TRAP fcphase,
const KS_EPI epi,
const char *  desc 
)
906  {
907 
908  /* set time origin at end of bipolar flow comp lobe/beginning of epi.blipphaser */
909  float dummy1 = 0.0;
910  float dummy2 = 0.0;
911  float zeromomentsum = 0.0;
912  float firstmomentsum = 0.0;
913  int pulsepos = 0;
914  int invertphase = 0;
915  int pulsecnt;
916  int epiesp = 0;
917 
918  epiesp = (epi->read.grad.duration + epi->read_spacing);
919 
920  /* compute moments for blips */
921  pulsepos = epi->blipphaser.grad.duration + epiesp - epi->blip.duration / 2;
922 
923  int blips2cent = ((epi->blipphaser.nover != 0) ? (epi->blipphaser.nover / epi->blipphaser.R) : (epi->etl / 2)) - 1;
924 
925  for (pulsecnt = 0; pulsecnt < blips2cent; pulsecnt++) {
926  /* N.B.: pulsepos is updated in rampmoments() */
927  rampmoments(0.0, epi->blip.amp, epi->blip.ramptime, invertphase, &pulsepos, &dummy1, &dummy2, &zeromomentsum, &firstmomentsum);
928  rampmoments(epi->blip.amp, epi->blip.amp, epi->blip.plateautime, invertphase, &pulsepos, &dummy1, &dummy2, &zeromomentsum, &firstmomentsum);
929  rampmoments(epi->blip.amp, 0.0, epi->blip.ramptime, invertphase, &pulsepos, &dummy1, &dummy2, &zeromomentsum, &firstmomentsum);
930  pulsepos += (epiesp - epi->blip.duration);
931  }
932 
933  ks_init_trap(fcphase);
934 
935  if (!areSame(zeromomentsum, 0) && !areSame(firstmomentsum, 0)) {
936  int fcramp, fcplateau, dummy;
937  float fcamp;
938  amppwygmn(zeromomentsum, firstmomentsum, epi->blipphaser.grad.ramptime, epi->blipphaser.grad.plateautime, epi->blipphaser.grad.ramptime,
939  0.0, 0.0, (double) ks_syslimits_ampmax(loggrd), (double) ks_syslimits_ramptimemax(loggrd), 0,
940  &fcramp, &fcplateau, &dummy, &fcamp);
941 
942  fcphase->amp = fcamp;
943  fcphase->ramptime = fcramp;
944  fcphase->plateautime = fcplateau;
945  fcphase->duration = 2 * fcphase->ramptime + fcphase->plateautime;
946  fcphase->area = fcphase->duration * ((float) fcphase->ramptime + fcphase->plateautime);
947  sprintf(fcphase->description, desc);
948  }
949 
950  return SUCCESS;
951 
952 } /* ksepi_eval_flowcomp() */
KS_TRAP blip
Definition: KSFoundation.h:1839
int plateautime
Definition: KSFoundation.h:584
int R
Definition: KSFoundation.h:1680
#define areSame(a, b)
Definition: KSFoundation.h:119
KS_TRAP grad
Definition: KSFoundation.h:1676
float ks_syslimits_ampmax(LOG_GRAD loggrd)
Returns the maximum gradient amplitude that can be used on all gradient boards simultaneously
Definition: KSFoundation_common.c:201
KS_PHASER blipphaser
Definition: KSFoundation.h:1840
KS_TRAP grad
Definition: KSFoundation.h:1586
int ks_syslimits_ramptimemax(LOG_GRAD loggrd)
Returns the minimum ramp time to get from zero to full gradient scale
Definition: KSFoundation_common.c:234
int etl
Definition: KSFoundation.h:1843
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
LOG_GRAD loggrd
KS_READTRAP read
Definition: KSFoundation.h:1837
float area
Definition: KSFoundation.h:582
float amp
Definition: KSFoundation.h:581
int nover
Definition: KSFoundation.h:1679
KS_DESCRIPTION description
Definition: KSFoundation.h:580
int read_spacing
Definition: KSFoundation.h:1844
int duration
Definition: KSFoundation.h:585
int ramptime
Definition: KSFoundation.h:583

◆ ksepi_pg()

STATUS ksepi_pg ( int  start_time)

The ksepi (main) pulse sequence

This is the main pulse sequence in ksepi.e using the sequence objects in KSEPI_SEQUENCE with the sequence module name "ksepimain" (= ksepi.seqctrl.description)

Return values
STATUSSUCCESS or FAILURE
1958  {
1959  KS_SEQLOC tmploc = KS_INIT_SEQLOC;
1960  int epi_startpos = KS_NOTSET;
1961  int epi_readout_startpos = KS_NOTSET;
1962  int fc_startpos = KS_NOTSET;
1963  int fcz_endpos = KS_NOTSET;
1964  int echo, board;
1965 
1966  if (start_time < KS_RFSSP_PRETIME) {
1967  return ks_error("%s: 1st arg (pos start) must be at least %d us", __FUNCTION__, KS_RFSSP_PRETIME);
1968  }
1969 
1970 #ifdef HOST_TGT
1971  if (opte < avminte) {
1972  /* we cannot proceed until TE is in range.
1973  Return a long seq duration and pretend all is good */
1975  return SUCCESS;
1976  }
1977 #endif
1978 
1979 
1980  /*******************************************************************************************************
1981  * RF Excitation
1982  *******************************************************************************************************/
1983  tmploc.ampscale = 1.0;
1984  tmploc.pos = RUP_GRD(start_time + KS_RFSSP_PRETIME);
1985  tmploc.board = ZGRAD;
1986 
1987  /* N.B.: ks_pg_selrf()->ks_pg_rf() detects that ksepi.selrfexc is an excitation pulse
1988  (ksepi.selrfexc.rf.role = KS_RF_ROLE_EXC) and will also set ksepi.seqctrl.momentstart
1989  to the absolute position in [us] of the isocenter of the RF excitation pulse */
1990  if (ks_pg_selrf(&ksepi.selrfexc, tmploc, &ksepi.seqctrl) == FAILURE)
1991  return FAILURE;
1992 
1993  /* forward to end of selrfexc.postgrad (works for when slice sel gradient is KS_TRAP or KS_WAVE as only
1994  one of them can have non-zero duration at a given time) */
1996 
1997  /*******************************************************************************************************
1998  * Flow clomp in slice dir
1999  *******************************************************************************************************/
2000 
2001  /* First flow comp gradient was already merged into selrf rephaser */
2002  /* Second flow comp gradient slice for slice excitation */
2003  if (ks_pg_trap(&ksepi.fcompslice, tmploc, &ksepi.seqctrl) == FAILURE) /* N.B.: will return quietly if ksepi.fcompslice.duration = 0 (opfcomp = 0) */
2004  return FAILURE;
2005  fcz_endpos = tmploc.pos + ksepi.fcompslice.duration;
2006 
2007  /*******************************************************************************************************
2008  * EPI phase reference lines
2009  *******************************************************************************************************/
2011  tmploc.pos = fcz_endpos;
2012  if (ksepi_slicecheck == FALSE) { /* reflines dephaser may overlap with slice flow comp and selrf rephaser unless slicecheck mode */
2014  }
2015  tmploc.ampscale = ksepi_readsign;
2016  if (ks_pg_epi(&ksepi.dynreftrain, tmploc, &ksepi.seqctrl) == FAILURE)
2017  return FAILURE;
2018 
2019  /*******************************************************************************************************
2020  * EPI trains: Begin (> 1 only supported with offline recon)
2021  -------------------------------------------------------------------------------------------------------*/
2022  for (echo = 0; echo < opnecho; echo++) {
2023 
2024  if (acq_type == TYPSPIN) {
2025  if (opdiffuse && echo == 0) {
2026  if (ksepi_diffusion_pg(&ksepi, opte) == FAILURE)
2027  return FAILURE;
2028  } else {
2029  if (echo == 0) /* RF refocusing pulse for 1st EPI train at TE/2 */
2031  else /* RF refocusing pulse between two EPI trains (2nd-Nth EPI train are played out as tight as possible when ksepi_echogap = 0). Use epi_startpos from previous echo index (see below) */
2032  tmploc.pos = epi_startpos + ksepi.epitrain.duration + KS_RFSSP_PRETIME + ksepi_echogap / 2;
2033  tmploc.board = ZGRAD;
2034  if (ks_pg_selrf(&ksepi.selrfref, tmploc, &ksepi.seqctrl) == FAILURE)
2035  return FAILURE;
2036  }
2037  } /* acq_type == TYPSPIN */
2038 
2039  epi_startpos = ksepi.seqctrl.momentstart + opte - ksepi.epitrain.time2center + (echo * ksepi_interechotime);
2040  epi_readout_startpos = epi_startpos + IMax(3, ksepi.epitrain.readphaser.duration,
2043 
2044  /*******************************************************************************************************
2045  * Flow comp in phase dir
2046  *******************************************************************************************************/
2047 
2048  fc_startpos = epi_readout_startpos - ksepi.epitrain.blipphaser.grad.duration - 2 * ksepi.fcompphase.duration;
2049  tmploc.board = YGRAD;
2050  tmploc.pos = fc_startpos;
2051  tmploc.ampscale = 1;
2052  if (ks_pg_trap(&ksepi.fcompphase, tmploc, &ksepi.seqctrl) == FAILURE) /* instance #0. N.B.: will return quietly if ksepi.fcompphase.duration = 0 */
2053  return FAILURE;
2054 
2055  tmploc.pos += ksepi.fcompphase.duration;
2056  tmploc.ampscale = -1;
2057  if (ks_pg_trap(&ksepi.fcompphase, tmploc, &ksepi.seqctrl) == FAILURE) /* instance #1 */
2058  return FAILURE;
2059 
2060  /*******************************************************************************************************
2061  * EPI readout including de/rephasers on freq, phase and slice encoding axes (net zero moment on both axes)
2062  *******************************************************************************************************/
2063 
2065  tmploc.pos = epi_startpos;
2066  tmploc.ampscale = ksepi_readsign;
2067  if (ks_pg_epi(&ksepi.epitrain, tmploc, &ksepi.seqctrl) == FAILURE)
2068  return FAILURE;
2069 
2070  /*******************************************************************************************************
2071  * EPI echo time shifting
2072  *******************************************************************************************************/
2073  if (ksepi_echotime_shifting == TRUE && echo == 0) {
2074  for (board = XGRAD; board <= SSP; board++) {
2075  tmploc.board = board;
2076  if (oppseq == PSD_SE) {
2077  /* 2D: SE-EPI or DW-EPI */
2078  tmploc.pos = epi_startpos - GRAD_UPDATE_TIME;
2079  } else {
2080  /* 2D/3D: GE-EPI
2081  Place wait pulses just before main epi train dephasers (incl flowcomp if present) */
2082  if ((board == XGRAD && ksepi_slicecheck == FALSE) || (board == ZGRAD && ksepi_slicecheck == TRUE)) {
2083  tmploc.pos = epi_readout_startpos - ksepi.epitrain.readphaser.duration - GRAD_UPDATE_TIME;
2084  } else if (board == YGRAD) {
2085  tmploc.pos = fc_startpos - GRAD_UPDATE_TIME;
2086  } else {
2087  tmploc.pos = epi_readout_startpos - ksepi.epitrain.zphaser.grad.duration - GRAD_UPDATE_TIME;
2088  }
2089  }
2090  if (ks_pg_wait(&ksepi.pre_delay, tmploc, &ksepi.seqctrl) != SUCCESS) {
2091  return FAILURE;
2092  }
2093  }
2094  }
2095 
2096 
2097  }
2098  /*------------------------------------------------------------------------------------------------------
2099  * EPI trains: End
2100  *******************************************************************************************************/
2101 
2102  /*******************************************************************************************************
2103  * Gradient spoilers on Y and Z (at the same time)
2104  *******************************************************************************************************/
2105  tmploc.ampscale = 1.0;
2106  tmploc.pos = epi_startpos + ksepi.epitrain.duration;
2107  tmploc.board = YGRAD;
2108  if (ks_pg_trap(&ksepi.spoiler, tmploc, &ksepi.seqctrl) == FAILURE)
2109  return FAILURE;
2110  tmploc.board = ZGRAD;
2111  if (ks_pg_trap(&ksepi.spoiler, tmploc, &ksepi.seqctrl) == FAILURE)
2112  return FAILURE;
2113 
2114  tmploc.pos += ksepi.spoiler.duration;
2115 
2116  /*******************************************************************************************************
2117  * EPI echo time shifting (post EPI readouts)
2118  *******************************************************************************************************/
2119  if (ksepi_echotime_shifting == TRUE) {
2120  tmploc.pos += GRAD_UPDATE_TIME;
2121  tmploc.board = KS_ALL;
2122  if (ks_pg_wait(&ksepi.post_delay, tmploc, &ksepi.seqctrl) != SUCCESS) {
2123  return FAILURE;
2124  }
2125  tmploc.pos += IMax(2, psd_grd_wait, psd_rf_wait) + GRAD_UPDATE_TIME;
2127  }
2128 
2129  /*******************************************************************************************************
2130  * Set the minimal sequence duration (ksepi.seqctrl.min_duration) by calling
2131  * ks_eval_seqctrl_setminduration()
2132  *******************************************************************************************************/
2133 
2134  /* make sure we are divisible by GRAD_UPDATE_TIME (4us) */
2135  tmploc.pos = RUP_GRD(tmploc.pos);
2136 
2137 #ifdef HOST_TGT
2138  /* On HOST only: Sequence duration (ksepi.seqctrl.ssi_time must be > 0 and is added to ksepi.seqctrl.min_duration in ks_eval_seqctrl_setminduration() */
2140  ks_eval_seqctrl_setminduration(&ksepi.seqctrl, tmploc.pos); /* tmploc.pos now corresponds to the end of last gradient in the sequence */
2141 #endif
2142 
2143  /*******************************************************************************************************
2144  * Phase encoding table
2145  *
2146  * Need to call this in ksepi_pg() so it is run both on HOST and TGT. This, since the phase table
2147  * is dynamically allocated in ks_phaseencoding_generate_epi()->ks_phaseencoding_resize()
2148  *******************************************************************************************************/
2149  if (ks_phaseencoding_generate_epi(&ksepi.full_peplan, "Fully sampled EPI volume",
2150  &ksepi.epitrain,
2156  ksepi_caipi) == FAILURE) {
2157  return FAILURE;
2158  }
2159  if (ks_phaseencoding_generate_epi(&ksepi.ref_peplan, "EPI reference volume",
2160  &ksepi.epitrain,
2166  ksepi_caipi) == FAILURE) {
2167  return FAILURE;
2168  }
2169  if (ks_phaseencoding_generate_epi(&ksepi.peplan, "Accelerated EPI volume",
2170  &ksepi.epitrain,
2176  ksepi_caipi) == FAILURE) {
2177  return FAILURE;
2178  }
2180 
2181  /* KS_NOTSET -> turns off phase blips for phase reference lines */
2182  ks_scan_epi_shotcontrol(&ksepi.dynreftrain, 0, ks_scan_info[0], NULL, 0, /* exc */ KS_NOTSET, 0);
2183 
2184  /* set EPI dephasers and blips to the first shot so we get the correct plots in WTools */
2185  ks_scan_epi_shotcontrol(&ksepi.epitrain, 0, ks_scan_info[0], &ksepi.full_peplan, 0, /* exc */ 0, 0);
2186 
2187  return SUCCESS;
2188 
2189 } /* ksepi_pg() */
int ksepi_readsign
Definition: ksepi_implementation.e:127
KS_PHASEENCODING_PLAN ref_peplan
Definition: ksepi_implementation.e:63
Definition: KSFoundation.h:1919
KS_TRAP grad
Definition: KSFoundation.h:1491
int R
Definition: KSFoundation.h:1680
int start2iso
Definition: KSFoundation.h:944
KS_TRAP grad
Definition: KSFoundation.h:1676
KS_SELRF selrfexc
Definition: ksepi_implementation.e:53
int pos
Definition: KSFoundation.h:389
#define KS_NOTSET
Definition: KSFoundation.h:103
int ksepi_echotime_shifting
Definition: ksepi_implementation.e:136
KS_WAVE gradwave
Definition: KSFoundation.h:1493
KS_PHASEENCODING_PLAN peplan
Definition: ksepi_implementation.e:64
int ksepi_eval_ssitime()
The SSI time for the sequence
Definition: ksepi_implementation.e:1679
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
KS_TRAP fcompphase
Definition: ksepi_implementation.e:60
ks_enum_sweep_order
Definition: KSFoundation.h:1902
KS_PHASER blipphaser
Definition: KSFoundation.h:1840
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
int numlinestoacq
Definition: KSFoundation.h:1684
KS_EPI dynreftrain
Definition: ksepi_implementation.e:51
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
STATUS ks_pg_wait(KS_WAIT *wait, KS_SEQLOC loc, KS_SEQ_CONTROL *ctrl) WARN_UNUSED_RESULT
Places a KS_WAIT sequence object on all boards at some position in the pulse sequence
Definition: KSFoundation_common.c:2287
int board
Definition: KSFoundation.h:388
KS_PHASER zphaser
Definition: KSFoundation.h:1841
Definition: KSFoundation.h:1924
int ksepi_ky_R
Definition: ksepi_implementation.e:139
float ampscale
Definition: KSFoundation.h:390
KS_EPI epitrain
Definition: ksepi_implementation.e:50
Definition: KSFoundation.h:1926
KS_TRAP pregrad
Definition: KSFoundation.h:1490
int duration
Definition: KSFoundation.h:1845
int ksepi_interechotime
Definition: ksepi_implementation.e:204
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:49
KS_RF rf
Definition: KSFoundation.h:1485
KS_SELRF selrfref
Definition: ksepi_implementation.e:54
KS_TRAP fcompslice
Definition: ksepi_implementation.e:61
STATUS ks_pg_epi(KS_EPI *epi, KS_SEQLOC loc, KS_SEQ_CONTROL *ctrl) WARN_UNUSED_RESULT
Places out a KS_EPI object (EPI train including dephaser and rephaser gradients)
Definition: KSFoundation_common.c:2704
Definition: KSFoundation.h:1902
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
typedef struct used as argument to ks_pg_*** functions to control where and when to place a sequence ...
Definition: KSFoundation.h:387
int ksepi_ref_nsegments
Definition: ksepi_implementation.e:179
KS_TRAP postgrad
Definition: KSFoundation.h:1492
STATUS ksepi_diffusion_pg(KSEPI_SEQUENCE *ksepi, int TE)
Definition: ksepi_implementation_diffusion.e:795
STATUS ks_phaseencoding_generate_epi(KS_PHASEENCODING_PLAN *phaseenc_plan_ptr, const char *const desc, const KS_EPI *epitrain, const ks_enum_epiblipsign blipsign, const ks_enum_pf_earlylate_te pf_direction, const int numileavestoacq, ks_enum_sweep_order sweep_order, int numsegments, const int caipi_delta)
EPI: Makes a KS_PHASEENCODING_PLAN suitable for 2D or 3D epi
Definition: KSFoundation_common.c:833
KS_PHASEENCODING_PLAN full_peplan
Definition: ksepi_implementation.e:62
int ssi_time
Definition: KSFoundation.h:1134
int ksepi_blipsign
Definition: ksepi_implementation.e:135
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_TRAP spoiler
Definition: ksepi_implementation.e:52
ks_enum_epiblipsign
Definition: KSFoundation.h:1929
int time2center
Definition: KSFoundation.h:1846
KS_PHASEENCODING_PLAN * current_peplan
Definition: ksepi_implementation.e:65
KS_TRAP readphaser
Definition: KSFoundation.h:1838
int ksepi_echotime_shifting_sumdelay
Definition: ksepi_implementation.e:210
int psd_grd_wait
void ks_scan_epi_shotcontrol(KS_EPI *epi, int echo, SCAN_INFO sliceinfo, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot, int exc, float rcvphase)
Changes the gradient state of a KS_EPI object for the given slice information
Definition: KSFoundation_tgt.c:1089
int ksepi_echogap
Definition: ksepi_implementation.e:126
#define KS_INIT_SEQLOC
Definition: KSFoundation.h:208
int duration
Definition: KSFoundation.h:585
int ksepi_slicecheck
Definition: ksepi_implementation.e:109
int psd_rf_wait
KS_WAIT pre_delay
Definition: ksepi_implementation.e:58
int ramptime
Definition: KSFoundation.h:583
endif SCAN_INFO ks_scan_info[SLTAB_MAX]
Definition: GERequired.e:215
int duration
Definition: KSFoundation.h:668
KS_WAIT post_delay
Definition: ksepi_implementation.e:59
Definition: KSFoundation.h:1899
#define KS_RFSSP_PRETIME
Definition: KSFoundation.h:152
int ksepi_caipi
Definition: ksepi_implementation.e:142

◆ ksepi_scan_coreslice()

int ksepi_scan_coreslice ( const SCAN_INFO *  slice_pos,
int  dabslice,
int  shot 
)

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 (ksepi_scan_seqstate()) and plays out the core ksepi 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 ksepi_eval_tr()) we call ksepi_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 ksepi_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]shotLinear ky kz shot index in range [0, (ksepi.peplan.num_shots-1)]
Return values
coreslicetimeTime taken in [us] to play out one slice with potentially other sequence modules
2444  {
2445  int echo;
2446  int time = 0;
2447  float tloc = 0.0;
2448  SCAN_INFO slice_pos_updated;
2449  KS_MAT4x4 Mphysical = KS_MAT4x4_IDENTITY;
2450  const KS_MAT4x4 Identity = KS_MAT4x4_IDENTITY;
2451 
2452  if (slice_pos != NULL)
2453  tloc = slice_pos->optloc;
2454 
2455  /*******************************************************************************************************
2456  * Update slice info
2457  *******************************************************************************************************/
2458  if (slice_pos != NULL) {
2459  ks_scan_update_slice_location(&slice_pos_updated, *slice_pos, Mphysical, Identity);
2460  }
2461 
2462  /*******************************************************************************************************
2463  * SpSat sequence module
2464  *******************************************************************************************************/
2466 
2467 
2468  /*******************************************************************************************************
2469  * Chemsat sequence module
2470  *******************************************************************************************************/
2473  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 */
2474 
2475 
2476  /*******************************************************************************************************
2477  * ksepi main sequence module
2478  *******************************************************************************************************/
2479  if (slice_pos != NULL) {
2480  /* modify sequence for next playout. If not entry point scan (e.g. L_REF), use no ky phase encodes */
2481  ksepi_scan_seqstate(slice_pos_updated, (rspent == L_SCAN) ? shot : KS_NOTSET);
2482  } else {
2483  /* false slice, shut off RF */
2485  }
2486 
2487  /* data routing control */
2488  KS_PHASEENCODING_COORD coord = ks_phaseencoding_get(ksepi.current_peplan, 0, shot); /* coord to first line of EPI train */
2489  if (KS_3D_SELECTED) {
2490  if (ks_scan_info[1].optloc > ks_scan_info[0].optloc)
2491  dabslice = (opslquant * opvquant - 1) - coord.kz;
2492  else
2493  dabslice = coord.kz;
2494  }
2495  for (echo = 0; echo < opnecho; echo++) {
2496  ks_scan_epi_loadecho(&ksepi.epitrain, echo, echo, dabslice, ksepi.current_peplan, shot);
2497  }
2498  if (ksepi_reflines > 0) {
2499  /* store phase reference lines as opnecho:th echo */
2500  ks_scan_epi_loadecho(&ksepi.dynreftrain, 0, opnecho, dabslice, ksepi.current_peplan, shot);
2501  }
2502 
2504  ks_plot_slicetime(&ksepi.seqctrl, 1, &tloc, opslthick, slice_pos == NULL ? KS_PLOT_NO_EXCITATION : KS_PLOT_STANDARD);
2505 
2506  return time; /* in [us] */
2507 
2508 } /* ksepi_scan_coreslice() */
int ksspsat_scan_playsequences(int perform_slicetimeplot)
Definition: KSSpSat.e:819
KSCHEMSAT_SEQUENCE kschemsat
Definition: KSChemSat.e:89
#define KS_NOTSET
Definition: KSFoundation.h:103
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
double KS_MAT4x4[16]
Definition: KSFoundation.h:265
STATUS ksepi_scan_seqstate(SCAN_INFO slice_info, int shot)
Sets the current state of all ksepi sequence objects being part of KSEPI_SEQUENCE
Definition: ksepi_implementation.e:2337
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
KS_EPI dynreftrain
Definition: ksepi_implementation.e:51
void ks_scan_epi_loadecho(KS_EPI *epi, int echo, int storeecho, int slice, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot)
Definition: KSFoundation_tgt.c:1270
KS_EPI epitrain
Definition: ksepi_implementation.e:50
int kz
Definition: KSFoundation.h:1706
#define KS_MAT4x4_IDENTITY
Definition: KSFoundation.h:256
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_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:49
int ks_scan_playsequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1368
Definition: KSFoundation.h:336
Definition: KSFoundation.h:335
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
void ksepi_scan_rf_off()
Sets all RF pulse amplitudes to zero
Definition: ksepi_implementation.e:2406
KS_PHASEENCODING_PLAN * current_peplan
Definition: ksepi_implementation.e:65
int ksepi_reflines
Definition: ksepi_implementation.e:162
void ks_scan_update_slice_location(SCAN_INFO *new_loc, const SCAN_INFO orig_loc, const KS_MAT4x4 M_physical, const KS_MAT4x4 M_logical)
Updates a SCAN_INFO struct using physical and logical 4x4 transformation matrices
Definition: KSFoundation_common.c:3186
int rspent
Definition: GERequired.e:2626
KS_SEQ_CONTROL seqctrl
Definition: KSChemSat.e:71
float opslthick
endif SCAN_INFO ks_scan_info[SLTAB_MAX]
Definition: GERequired.e:215

◆ ksepi_scan_coreslice_nargs()

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

Wrapper function to ksepi_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 ksepi_scan_sliceloop() in ksepi_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 ksepi_scan_coreslice_nargs() wrapper function provides the argument translation for ksepi_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 ksepi_scan_coreslice()) are stored in the generic void pointer array with nargs elements, which is then unpacked before calling ksepi_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 ksepi_scan_coreslice() in range [0,2]
[in]argsVoid pointer array pointing to the variables containing the actual values needed for ksepi_scan_coreslice()
Return values
coreslicetimeTime taken in [us] to play out one slice with potentially other sequence modules
2537  {
2538  int shot = 0;
2539 
2540  if (nargs < 0 || nargs > 1) {
2541  ks_error("%s: 4th arg (void **) must contain 0-1 elements (shot), not %d", __FUNCTION__, nargs);
2542  return -1;
2543  } else if (nargs > 0 && args == NULL) {
2544  ks_error("%s: 4th arg (void **) cannot be NULL if nargs (3rd arg) != 0", __FUNCTION__);
2545  return -1;
2546  }
2547 
2548  if (nargs >= 1 && args[0] != NULL) {
2549  shot = *((int *) args[0]);
2550  }
2551 
2552  return ksepi_scan_coreslice(slice_pos, dabslice, shot); /* in [us] */
2553 
2554 } /* ksepi_scan_coreslice_args() */
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int ksepi_scan_coreslice(const SCAN_INFO *slice_pos, int dabslice, int shot)
Plays out one slice in real time during scanning together with other active sequence modules...
Definition: ksepi_implementation.e:2444

◆ ksepi_scan_sliceloop()

int ksepi_scan_sliceloop ( int  slperpass,
int  volindx,
int  passindx,
int  shot 
)

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 ksepi_scan_coreslice() to play out one coreslice (i.e. the main ksepi main sequence + optional sequence modules, excluding inversion modules).

Parameters
[in]slperpassNumber of slices to play in the slice loop
[in]volindxVolume index in range [0, opfphases - 1]
[in]passindxPass index in range [0, ks_slice_plan.npasses - 1]
[in]shotLinear ky kz shot index in range [0, (ksepi.peplan.num_shots-1)]
Return values
slicelooptimeTime taken in [us] to play out slperpass slices
2602  {
2603  int time = 0;
2604  int slloc, sltimeinpass;
2605  SCAN_INFO centerposition = ks_scan_info[0]; /* first slice chosen here, need only rotation stuff */
2606 
2607  (void) volindx;
2608 
2609  if (KS_3D_SELECTED) {
2610  int centerslice = opslquant/2;
2611  /* for future 3D multislab support, let passindx update centerposition */
2612  centerposition.optloc = (ks_scan_info[centerslice-1].optloc + ks_scan_info[centerslice].optloc)/2.0;
2613  }
2614 
2615 
2616  for (sltimeinpass = 0; sltimeinpass < slperpass; sltimeinpass++) {
2617 
2618  SCAN_INFO *current_slice = &centerposition;
2619  if (!KS_3D_SELECTED) {
2620  /* slice location from slice plan */
2621  slloc = ks_scan_getsliceloc(&ks_slice_plan, passindx, sltimeinpass);
2622  current_slice = (slloc != KS_NOTSET) ? &ks_scan_info[slloc] : NULL;
2623  }
2624  time += ksepi_scan_coreslice(current_slice, sltimeinpass, shot);
2625 
2626  }
2627 
2628  return time; /* in [us] */
2629 
2630 } /* ksepi_scan_sliceloop() */
int volindx
Definition: ksfse_implementation.e:2849
#define KS_NOTSET
Definition: KSFoundation.h:103
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
int ksepi_scan_coreslice(const SCAN_INFO *slice_pos, int dabslice, int shot)
Plays out one slice in real time during scanning together with other active sequence modules...
Definition: ksepi_implementation.e:2444
int passindx
Definition: ksfse_implementation.e:2849
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
endif SCAN_INFO ks_scan_info[SLTAB_MAX]
Definition: GERequired.e:215

◆ ksepi_scan_sliceloop_nargs()

int ksepi_scan_sliceloop_nargs ( int  slperpass,
int  nargs,
void **  args 
)

Wrapper function to ksepi_scan_sliceloop() with standardized input arguments

For TR timing heat/SAR calculations of regular 2D multislice sequences, GEReq_eval_TR(), ks_eval_mintr() and GEReq_eval_checkTR_SAR() use a standardized function pointer with a fixed set of input arguments to call the sliceloop of the main sequence with different number of slices to check current slice loop duration. As different pulse sequences may need different number of input arguments (with different meaning) this ksepi_scan_sliceloop_nargs() wrapper function provides the argument translation for ksepi_scan_sliceloop().

The function pointer must have an integer corresponding to the number of slices to use as its first argument while the remaining input arguments (to ksepi_scan_sliceloop()) are stored in the generic void pointer array with nargs elements, which is then unpacked before calling ksepi_scan_sliceloop().

Parameters
[in]slperpassNumber of slices to play in the slice loop
[in]nargsNumber of extra input arguments to ksepi_scan_sliceloop() in range [0,3]
[in]argsVoid pointer array pointing to the variables containing the actual values needed for ksepi_scan_sliceloop()
Return values
slicelooptimeTime taken in [us] to play out slperpass slices
2709  {
2710  int volindx = 0;
2711  int passindx = 0;
2712  int shot = KS_NOTSET; /* off */
2713 
2714  if (nargs < 0 || nargs > 3) {
2715  ks_error("%s: 3rd arg (void **) must contain up to 3 elements: volindx, passindx, shot. Not %d", __FUNCTION__, nargs);
2716  return -1;
2717  } else if (nargs > 0 && args == NULL) {
2718  ks_error("%s: 3rd arg (void **) cannot be NULL if nargs (2nd arg) != 0", __FUNCTION__);
2719  return -1;
2720  }
2721 
2722  if (nargs >= 1 && args[0] != NULL) {
2723  volindx = *((int *) args[0]);
2724  }
2725  if (nargs >= 2 && args[1] != NULL) {
2726  passindx = *((int *) args[1]);
2727  }
2728  if (nargs >= 3 && args[2] != NULL) {
2729  shot = *((int *) args[2]);
2730  }
2731 
2732  return ksepi_scan_sliceloop(slperpass, volindx, passindx, shot); /* in [us] */
2733 
2734 } /* ksepi_scan_sliceloop_nargs() */
int volindx
Definition: ksfse_implementation.e:2849
#define KS_NOTSET
Definition: KSFoundation.h:103
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int passindx
Definition: ksfse_implementation.e:2849
int ksepi_scan_sliceloop(int slperpass, int volindx, int passindx, int shot)
Plays out slperpass slices corresponding to one TR
Definition: ksepi_implementation.e:2602

◆ ksepi_scan_seqstate()

STATUS ksepi_scan_seqstate ( SCAN_INFO  slice_info,
int  shot 
)

Sets the current state of all ksepi sequence objects being part of KSEPI_SEQUENCE

This function sets the current state of all ksepi sequence objects being part of KSEPI_SEQUENCE, incl. gradient amplitude changes, RF freq/phases and receive freq/phase based on current slice position and phase encoding indices.

The idea of having a 'seqstate' function is to be able to come back to a certain sequence state at any time and possibly play it out once more. This could for example be useful when certain lines or slices need to be rescanned due to image artifacts detected during scanning.

Parameters
[in]slice_infoPosition of the slice to be played out (one element in the ks_scan_info[] array)
[in]shotLinear ky kz shot index in range [0, (ksepi.peplan.num_shots-1)]
Return values
STATUSSUCCESS or FAILURE
2337  {
2338  int echo;
2339  float exc_rfphase;
2340  int exc = 0; /* NEX index. Future use */
2341 
2342  /* RF frequency & phase */
2343  if (ksepi_rfspoiling) {
2346  } else {
2347  exc_rfphase = 0;
2348  }
2349 
2350 
2351  ks_scan_rotate(slice_info);
2352 
2353  ks_scan_rf_on(&ksepi.selrfexc.rf, INSTRALL);
2354  ks_scan_rf_on(&ksepi.selrfref.rf, INSTRALL);
2355 
2356  ks_scan_selrf_setfreqphase(&ksepi.selrfexc, 0, slice_info, exc_rfphase);
2357  ks_scan_selrf_setfreqphase(&ksepi.selrfref, INSTRALL, slice_info, exc_rfphase+90);
2358 
2359  if (opdiffuse && opdualspinecho) {
2361  ks_scan_selrf_setfreqphase(&ksepi.selrfref2, 0, slice_info, exc_rfphase+90);
2362  }
2363 
2364  /* EPI echoes (i.e. EPI trains) */
2365  for (echo = 0; echo < opnecho; echo++) {
2366  ks_scan_epi_shotcontrol(&ksepi.epitrain, echo, slice_info, ksepi.current_peplan, shot, exc, exc_rfphase);
2367  } /* opnecho */
2368  ks_scan_epi_shotcontrol(&ksepi.dynreftrain, 0, slice_info, NULL, KS_NOTSET, KS_NOTSET, exc_rfphase);
2369 
2370  return SUCCESS;
2371 
2372 } /* ksepi_scan_seqstate() */
void ks_scan_rf_on(KS_RF *rf, int instanceno)
Resets the amplitude of one or all instances of an RF pulse (KS_RF)
Definition: KSFoundation_tgt.c:442
float ks_scan_rf_phase_spoiling(int counter)
Returns spoiling phase for a given RF counter
Definition: KSFoundation_common.c:3883
int ksepi_rfspoiling
Definition: ksepi_implementation.e:111
KS_SELRF selrfexc
Definition: ksepi_implementation.e:53
#define KS_NOTSET
Definition: KSFoundation.h:103
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
KS_EPI dynreftrain
Definition: ksepi_implementation.e:51
KS_EPI epitrain
Definition: ksepi_implementation.e:50
void ks_scan_selrf_setfreqphase(KS_SELRF *selrf, int instanceno, SCAN_INFO sliceinfo, float rfphase)
Updates the frequency and phase of one or all instances of a slice selective RF pulse (KS_SELRF)...
Definition: KSFoundation_tgt.c:581
KS_RF rf
Definition: KSFoundation.h:1485
KS_SELRF selrfref
Definition: ksepi_implementation.e:54
void ks_scan_rotate(SCAN_INFO slice_info)
Performs a rotation of the logical system on hardware (WARP)
Definition: KSFoundation_tgt.c:989
KS_PHASEENCODING_PLAN * current_peplan
Definition: ksepi_implementation.e:65
void ks_scan_epi_shotcontrol(KS_EPI *epi, int echo, SCAN_INFO sliceinfo, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot, int exc, float rcvphase)
Changes the gradient state of a KS_EPI object for the given slice information
Definition: KSFoundation_tgt.c:1089
KS_SELRF selrfref2
Definition: ksepi_implementation.e:55
int rfspoiling_phase_counter
Definition: ksepi_implementation.e:2897

◆ ksepi_scan_acqloop()

float ksepi_scan_acqloop ( int  passindx,
int  volindx,
int  multishotflag 
)

Plays out all phase encodes for all slices belonging to one pass

This function traverses through all shots (ksepi_numshots) to be played out and runs the ksepi_scan_sliceloop() for each set of shots and excitation. If ksepi_dda > 0, dummy scans will be played out before the phase encoding begins.

In the case of inversion, ksinv_scan_sliceloop() is called instead of ksepi_scan_sliceloop(), where the former takes a function pointer to ksepi_scan_coreslice_nargs() in order to be able to play out the coreslice in a timing scheme set by ksinv_scan_sliceloop().

Parameters
[in]passindx0-based pass index in range [0, ks_slice_plan.npasses - 1]
[in]volindx0-based image volume index in range [0, opfphases - 1]
[in]multishotflagksepi.epitrain.blipphaser.R is used as... 0: Parallel imaging factor 1: Multi-shot (all volumes, KSEPI_MULTISHOT_ON) 2: Multi-shot (multishot vol 1 (volindx=0), PI for vols 2-N, KSEPI_MULTISHOT_ON_VOL1) 3: Multi-shot (multishot for b0 volumes), PI for diffusion volumes (only when opdiffuse > 0)
Return values
passlooptimeTime taken in [us] to play out all phase encodes and excitations for slperpass slices. Note that the value is a float instead of int to avoid int overrange at 38 mins of scanning
2763  {
2764  float time = 0.0;
2765  int shot, kyshot;
2766  KS_PHASEENCODING_COORD coord;
2767  int ndummies = 0;
2768  int is_multishot = (multishotflag == KSEPI_MULTISHOT_ALLVOLS) || \
2769  (multishotflag == KSEPI_MULTISHOT_1STVOL && (volindx == 0)) || \
2770  (multishotflag == KSEPI_MULTISHOT_B0VOLS && opdiffuse && (volindx < opdifnumt2));
2771 
2772  if (ksepi_ghostcorr && volindx == -1) { /* reference volume */
2774  } else if (is_multishot) { /* multishot volume */
2776  } else { /* accelerated volume */
2778  }
2779 
2780  if (ksepi_fleet && volindx == -ksepi_fleet - ksepi_ghostcorr) { /* FLEET volume */
2782  }
2783  else { /* non-FLEET volumes */
2784  if (volindx == 0)
2785  ndummies = ksepi_dda;
2786  else
2787  ndummies = 0;
2788 
2789  for (shot = -ndummies; shot < ksepi.current_peplan->num_shots; shot++) {
2790 
2791  if (shot == 0 && ndummies > 0) {
2793  }
2794 
2795  if (ksepi_echotime_shifting == TRUE) {
2796  coord = ks_phaseencoding_get(ksepi.current_peplan, 0, shot); /* coord to first line of EPI train */
2797  kyshot = coord.ky % ksepi.current_peplan->phaser->R;
2798 
2800  int post_delay = 0;
2801 
2802  if (blipsign == KS_EPI_POSBLIPS) {
2803  post_delay = (kyshot <= 0) ? GRAD_UPDATE_TIME : RUP_GRD((int) (ksepi_echotime_shifting_shotdelay * kyshot));
2804  } else if (blipsign == KS_EPI_NEGBLIPS) {
2805  post_delay = (kyshot <= 0) ? GRAD_UPDATE_TIME : RUP_GRD((int) (ksepi_echotime_shifting_shotdelay * (ksepi.current_peplan->phaser->R-1-kyshot)));
2806  }
2807 
2809  ks_scan_wait(&ksepi.post_delay, post_delay);
2810  }
2811 
2812  if (ksinv1.params.irmode != KSINV_OFF) {
2813  void *args[] = {(void *) &shot}; /* pass on args via ksinv_scan_sliceloop() to ksepi_scan_coreslice() */
2814  int nargs = sizeof(args) / sizeof(void *);
2816  (shot < 0) ? KSINV_LOOP_DUMMY : KSINV_LOOP_NORMAL, ksepi_scan_coreslice_nargs, nargs, args);
2817  } else {
2819  }
2820 
2821  ks_plot_slicetime_endofslicegroup(volindx < 0 ? "ksepi ghostcorr" : "ksepi shots");
2822 
2823  /* save a frame of the main sequence */
2824  if (shot >= 0) {
2826  }
2827 
2828  } /* for shot */
2830  }
2831 
2832  return time; /* in [us] */
2833 
2834 } /* ksepi_scan_acqloop() */
int volindx
Definition: ksfse_implementation.e:2849
KS_PHASEENCODING_PLAN ref_peplan
Definition: ksepi_implementation.e:63
int R
Definition: KSFoundation.h:1680
int num_shots
Definition: KSFoundation.h:1739
void ks_plot_slicetime_endofpass(KS_PLOT_PASS_MODE)
Definition: KSFoundation_common.c:3412
int ksepi_echotime_shifting
Definition: ksepi_implementation.e:136
KS_PHASEENCODING_PLAN peplan
Definition: ksepi_implementation.e:64
Definition: ksepi_implementation.e:91
int ksepi_fleet_scan_sliceloop(int slperpass, int volindx, int passindx)
Definition: ksepi_implementation.e:2634
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
float ksepi_echotime_shifting_shotdelay
Definition: ksepi_implementation.e:207
KSINV_SEQUENCE ksinv1
Definition: KSInversion.e:126
void ks_plot_tgt_addframe(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_common.c:3488
int ky
Definition: KSFoundation.h:1705
const KS_PHASER * phaser
Definition: KSFoundation.h:1743
void ks_plot_slicetime_endofslicegroup(const char *desc)
Definition: KSFoundation_common.c:3428
int irmode
Definition: KSInversion.e:76
KS_EPI epitrain
Definition: ksepi_implementation.e:50
ks_enum_epiblipsign ks_scan_epi_verify_phaseenc_plan(KS_EPI *epi, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot)
Definition: KSFoundation_tgt.c:1050
int nslices_per_pass
Definition: KSFoundation.h:1353
Definition: KSFoundation.h:339
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_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:49
int ksepi_scan_coreslice_nargs(const SCAN_INFO *slice_pos, int dabslice, int nargs, void **args)
Wrapper function to ksepi_scan_coreslice() with standardized input arguments
Definition: ksepi_implementation.e:2537
Definition: KSInversion.e:47
Definition: KSFoundation.h:1929
int ksinv_scan_sliceloop(const KS_SLICE_PLAN *slice_plan, const SCAN_INFO *slice_positions, int passindx, KSINV_SEQUENCE *ksinv1, KSINV_SEQUENCE *ksinv2, KS_SEQ_CONTROL *ksinv_filltr, KSINV_LOOP_MODE ksinv_loop_mode, int(*play_coreslice)(const SCAN_INFO *, int, int, void **), int core_nargs, void **core_args)
Plays out slice_plan.nslices_per_pass slices corresponding to one TR for inversion psds...
Definition: KSInversion.e:2257
int passindx
Definition: ksfse_implementation.e:2849
int ksepi_scan_sliceloop(int slperpass, int volindx, int passindx, int shot)
Plays out slperpass slices corresponding to one TR
Definition: ksepi_implementation.e:2602
Definition: ksepi_implementation.e:90
void ks_scan_wait(KS_WAIT *wait, int waitperiod)
Updates the wait period of all instances of a KS_WAIT sequence object. The value of waitperiod must n...
Definition: KSFoundation_tgt.c:151
KS_PHASEENCODING_PLAN full_peplan
Definition: ksepi_implementation.e:62
int ksepi_dda
Definition: ksepi_implementation.e:174
ks_enum_epiblipsign
Definition: KSFoundation.h:1929
Definition: ksepi_implementation.e:92
KSINV_SEQUENCE ksinv2
Definition: KSInversion.e:127
Definition: KSInversion.e:47
KS_PHASEENCODING_PLAN * current_peplan
Definition: ksepi_implementation.e:65
int ksepi_echotime_shifting_sumdelay
Definition: ksepi_implementation.e:210
KS_SLICE_PLAN ks_slice_plan
Definition: GERequired.e:217
Definition: KSFoundation.h:341
KSINV_PARAMS params
Definition: KSInversion.e:101
int ksepi_ghostcorr
Definition: ksepi_implementation.e:178
Definition: KSInversion.e:45
int ksepi_fleet
Definition: ksepi_implementation.e:153
KS_SEQ_CONTROL ksinv_filltr
Definition: KSInversion.e:128
KS_WAIT pre_delay
Definition: ksepi_implementation.e:58
Definition: KSFoundation.h:1929
Definition: KSFoundation.h:340
endif SCAN_INFO ks_scan_info[SLTAB_MAX]
Definition: GERequired.e:215
KS_WAIT post_delay
Definition: ksepi_implementation.e:59

◆ ksepi_scan_scanloop()

float ksepi_scan_scanloop ( )

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

This function performs the entire scan and traverses through passes and volumes. For each passindx (in range [0, ks_slice_plan.npasses-1]), and volindx, ksepi_scan_acqloop() will be called to acquire all data for the current set of slices belong to the current pass (acquisition).

Return values
scantimeTotal scan time in [us] (float to avoid int overrange after 38 mins)
2850  {
2851  float time = 0.0;
2852  int volindx, passindx;
2853 
2854  for (volindx = -ksepi_fleet - ksepi_ghostcorr; volindx < opfphases; volindx++) { /* opfphases = # volumes */
2855 
2856  if (ksepi_ghostcorr && volindx == -1) /* if ghostcorr is used it will be volume -1 */
2857  rspent = L_REF; /* will make zero phase encodes in ksepi_scan_coreslice() */
2858  else
2859  rspent = L_SCAN;
2860 
2861  if (opdiffuse) {
2863  }
2864 
2865  for (passindx = 0; passindx < ks_slice_plan.npasses; passindx++) {
2866 
2868 
2869 #ifdef IPG
2870  if ( !((volindx + 1 == opfphases) && (passindx + 1 == ks_slice_plan.npasses)) ) {
2871  GEReq_endofpass(); /* don't play last time, we rely now on GEReq_endofpassandscan() in ksepi.e:scan() */
2872  }
2873 #endif
2874 
2875  } /* end: acqs (pass) loop */
2876 
2877  } /* end: volume loop */
2878 
2879  return time; /* in [us] */
2880 
2881 } /* ksepi_scan_scanloop() */
int volindx
Definition: ksfse_implementation.e:2849
void ksepi_diffusion_scan_diffamp(KSEPI_SEQUENCE *ksepi, int volindx)
Definition: ksepi_implementation_diffusion.e:882
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
#define L_REF
Definition: KSFoundation.h:159
int npasses
Definition: KSFoundation.h:1352
int passindx
Definition: ksfse_implementation.e:2849
int GEReq_endofpass()
Sets SSP word in sequence off_GEpass() to trigger data (Pfile) writing and reconstruction
Definition: GERequired.e:2574
KS_SLICE_PLAN ks_slice_plan
Definition: GERequired.e:217
int rspent
Definition: GERequired.e:2626
int ksepi_ghostcorr
Definition: ksepi_implementation.e:178
float ksepi_scan_acqloop(int, int, int)
Plays out all phase encodes for all slices belonging to one pass
Definition: ksepi_implementation.e:2763
int ksepi_fleet
Definition: ksepi_implementation.e:153
int ksepi_multishot_control
Definition: ksepi_implementation.e:180

◆ ksepi_init_imagingoptions()

void ksepi_init_imagingoptions ( void  )

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

Returns
void
279  {
280  int numopts = sizeof(sequence_iopts) / sizeof(int);
281 
282  psd_init_iopt_activity();
283  activate_iopt_list(numopts, sequence_iopts);
284  enable_iopt_list(numopts, sequence_iopts);
285 
286  /* Imaging option control functions (using PSD_IOPT_ZIP_512 as example):
287  - Make an option unchecked and not selectable: disable_ioption(PSD_IOPT_ZIP_512)
288  - Make an option checked and not selectable: set_required_disabled_option(PSD_IOPT_ZIP_512)
289  - Remove the imaging option: deactivate_ioption(PSD_IOPT_ZIP_512)
290  */
291 
292  /* Do not allow 3D multislab to be selected until supported by the PSD */
293  cvmax(opimode, PSD_3D);
294 
295  /* Button accept control */
296  cvmax(opflair, OPFLAIR_GROUP); /* allow T2-FLAIR */
297  cvmax(opepi, 1);
298  cvdef(opepi, 1);
299  cvmax(opmph, 1);
300  cvmax(opdiffuse, 1);
301 
302  if (KS_3D_SELECTED) {
303  deactivate_ioption(PSD_IOPT_IR_PREP);
304  }
305 
306  /* flow comp only for GE-EPI */
307  if (exist(oppseq) == PSD_SE) {
308  deactivate_ioption(PSD_IOPT_FLOW_COMP);
309  }
310 
311  if (opflair) {
312  deactivate_ioption(PSD_IOPT_IR_PREP);
313  }
314 
315  if (opdiffuse) {
316  deactivate_ioption(PSD_IOPT_MPH);
317  }
318 
319 #ifdef SIM
320  opepi = !KS_3D_SELECTED;
321  setexist(opepi, PSD_ON);
322  opirmode = PSD_OFF; /* default interleaved slices */
323  setexist(opirmode, PSD_ON);
324 #endif
325 
326  /* GERequired.e:GEReq_cvinit() sets ks_qfact (acoustic reduction) when
327  ART (opsilent) has been selected. For medium/high ART, ks_qfact is set to 8/20.
328  However, for EPI, the geometric distortions becomes too severe so can no
329  reduce the slewrate for EPI as much (and hence the amount of acoustic reduction).
330 
331  Also the SPSP RF pulse uses a gradwave that cannot be derated.
332  If we use SPSP RF exc (opfat == FALSE), we set ks_qfact = 1.0.
333  With opfat ks_qfact will be set by GEReq_cvinit() and the sequence will run quieter
334  In all cases, the EPI readout gradients are controlled by ksepi_epiqfact */
335 
336  if (opsilent) {
337 
338  if (opfat == FALSE) {
339  /* SPectral-SPatial RF. Cannot derate excitation waveform */
340  ks_qfact = 1.0; /* for all gradients except the EPI readout */
342  }
343 
344  if (opsilentlevel == 1) {
345  /* moderate ART (small acoustic reduction) */
346  ksepi_epiqfact = 3.0;
347  } else {
348  /* high ART (moderate acoustic reduction) */
349  ksepi_epiqfact = 6.0; /* for the EPI readout */
350  }
351  } else {
352  ksepi_epiqfact = 1.0;
353  }
354 
355  pipure = PSD_PURE_COMPATIBLE_2; /* or maybe PSD_PURE_COMPATIBLE_1 ? */
356 
357 
358 } /* ksepi_init_imagingoptions() */
STATUS GEReq_init_gradspecs(LOG_GRAD *loggrd, PHYS_GRAD *phygrd, float srfact)
Initialize logical and physical gradient specifications
Definition: GERequired.e:393
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
PHYS_GRAD phygrd
float ks_qfact
Definition: GERequired.e:243
int sequence_iopts[]
Definition: ksepi_implementation.e:255
LOG_GRAD loggrd
float ksepi_epiqfact
Definition: ksepi_implementation.e:181
float ks_srfact
Definition: GERequired.e:242

◆ ksepi_init_UI()

STATUS ksepi_init_UI ( void  )

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

Return values
STATUSSUCCESS or FAILURE
368  {
369  STATUS status;
370 
371  /* Slice oversampling for 3D to avoid aliasing */
372  if (KS_3D_SELECTED) {
373  pislblank = ksepi_kissoff_factor * exist(opslquant);
374  }
375 
376  /* Spin or Gradient Echo EPI */
377  if (exist(oppseq) == PSD_SE || exist(oppseq) == PSD_IR) {
378  acq_type = TYPSPIN; /* SE, FLAIR, or Diffusion EPI */
379  } else {
380  acq_type = TYPGRAD; /* GRE-EPI */
381  }
382 
383  /* force flow comp off for non-GE-EPI */
384  if (acq_type != TYPGRAD) {
385  cvoverride(opfcomp, FALSE, PSD_FIX_ON, PSD_EXIST_ON);
386  }
387 
388  /* rBW */
389  pircbnub = (KS_3D_SELECTED) ? 4 : 5; /* number of variable bandwidth */
390  pircb2nub = 0; /* no second bandwidth option */
391  cvmin(oprbw, 15.625);
392  if (ksepi_rampsampling) {
393  cvmax(oprbw, (KS_3D_SELECTED) ? 125 : 250);
394  cvdef(oprbw, (KS_3D_SELECTED) ? 125 : 250);
395  pircbval2 = 31.25;
396  pircbval3 = 62.50;
397  pircbval4 = 125.0;
398  pircbval5 = (KS_3D_SELECTED) ? 125 : 250;
399  } else {
400  cvmax(oprbw, KSEPI_MAXRBW_NORAMPSAMPLING);
401  cvdef(oprbw, 62.5);
402  pircbval2 = 31.25;
403  pircbval3 = 62.50;
404  pircbval4 = 83.33;
405  pircbval5 = KSEPI_MAXRBW_NORAMPSAMPLING;
406  }
407  if (oprbw > _oprbw.maxval) {
408  /* this avoid minFOV errors for rBW = 250 when FOV < 35 cm */
409  cvoverride(oprbw, KSEPI_MAXRBW_NORAMPSAMPLING, _oprbw.fixedflag, _oprbw.existflag);
410  }
411  oprbw = _oprbw.defval;
412  pidefrbw = _oprbw.defval;
413 
414  /* NEX - never show. Partial Fourier in ky is done with opte = MINTE, not with NEX < 1 */
415  cvdef(opnex, 1);
416  opnex = _opnex.defval;
417  cvmin(opnex, 1);
418  cvmax(opnex, 1);
419  opnex = 1;
420  if (opdiffuse) {
421  cvoverride(opnex, 1, PSD_FIX_OFF, PSD_EXIST_ON);
422  pinexnub = 0;
423  } else {
424  pinexnub = 63;
425  }
426  pinexval2 = 1;
427  pinexval3 = 1;
428  pinexval4 = 1;
429  pinexval5 = 1;
430  pinexval6 = 1;
431 
432  /* FOV */
433  opfov = 240;
434  pifovnub = 5;
435  pifovval2 = 200;
436  pifovval3 = 220;
437  pifovval4 = 240;
438  pifovval5 = 260;
439  pifovval6 = 280;
440 
441  /* phase FOV fraction */
442  opphasefov = 1;
443  piphasfovnub2 = 63;
444  piphasfovval2 = 1.0;
445  piphasfovval3 = 0.9;
446  piphasfovval4 = 0.8;
447  piphasfovval5 = 0.7;
448  piphasfovval6 = 0.6;
449 
450  /* freq (x) resolution */
451  cvmin(opxres, 16);
452 
453  /* phase (y) resolution */
454  cvmin(opyres, 16);
455 
456  if (KS_3D_SELECTED) {
457  /* assuming many shots for 3D */
458  cvdef(opxres, 320);
459  pixresnub = 63;
460  pixresval2 = 192;
461  pixresval3 = 256;
462  pixresval4 = 288;
463  pixresval5 = 320;
464  pixresval6 = 384;
465 
466  cvdef(opyres, 320);
467  piyresnub = 63;
468  piyresval2 = 192;
469  piyresval3 = 256;
470  piyresval4 = 288;
471  piyresval5 = 320;
472  piyresval6 = 384;
473  } else {
474  cvdef(opxres, 64);
475  cvdef(opyres, 64);
476  if (opdiffuse) {
477  pixresnub = 63;
478  pixresval2 = 96;
479  pixresval3 = 128;
480  pixresval4 = 160;
481  pixresval5 = 192;
482  pixresval6 = 224;
483 
484  piyresnub = 63;
485  piyresval2 = 96;
486  piyresval3 = 128;
487  piyresval4 = 160;
488  piyresval5 = 192;
489  piyresval6 = 224;
490  } else {
491  pixresnub = 63;
492  pixresval2 = 32;
493  pixresval3 = 64;
494  pixresval4 = 96;
495  pixresval5 = 128;
496  pixresval6 = 160;
497 
498  piyresnub = 63;
499  piyresval2 = 32;
500  piyresval3 = 64;
501  piyresval4 = 96;
502  piyresval5 = 128;
503  piyresval6 = 160;
504  }
505  }
506  opxres = _opxres.defval;
507  opyres = _opyres.defval;
508 
509 
510  /* Num echoes */
511  piechnub = 63;
512  cvdef(opnecho, 1);
513  cvmax(opnecho, 8);
514  opnecho = _opnecho.defval;
515  piechdefval = _opnecho.defval;
516  piechval2 = 1;
517  piechval3 = 2;
518  piechval4 = 4;
519  piechval5 = 6;
520  piechval6 = 8;
521 
522  /* ETL */
523  cvmax(opetl, 1024);
524  pietlnub = 0;
525 
526  /* TE */
527  avmaxte = 1s;
528  avminte = 0;
529  avminte2 = 0;
530  pitetype = PSD_LABEL_TE_EFF; /* alt. PSD_LABEL_TE_EFF */
531  cvdef(opte, 200ms);
532  opte = _opte.defval;
533  pite1nub = 63;
534  pite1val2 = PSD_MINIMUMTE;
535  pite1val3 = PSD_MINFULLTE;
536  pite1val4 = 30ms;
537  pite1val5 = 50ms;
538  pite1val6 = 70ms;
539 
540  /* TE2 */
541  /* pite2nub = 0; */
542 
543  /* TR */
544  cvdef(optr, 2s);
545  optr = _optr.defval;
546  if (opfast == TRUE) {
547  pitrnub = 0; /* '0': shown but greyed out (but only if opautotr = 1, otherwise TR menu is hidden) */
548  cvoverride(opautotr, PSD_ON, PSD_FIX_OFF, PSD_EXIST_ON);
549  } else {
550  pitrnub = 6; /* '2': only one menu choice (Minimum = AutoTR) */
551  }
552  pitrval2 = PSD_MINIMUMTR;
553  pitrval3 = 1000ms;
554  pitrval4 = 2000ms;
555  pitrval5 = 3000ms;
556  pitrval6 = 4000ms;
557 
558  /* FA */
559  if (acq_type == TYPSPIN) {
560  cvdef(opflip, 180); /* refocusing RF: initialize with low FA to avoid gradrf complaints on load */
561  pifanub = 0; /* can also be e.g. 2 to allow modification of refocusing flip angle */
562  pifamode = PSD_FLIP_ANGLE_MODE_REFOCUS;
563  pifaval2 = 180;
564  } else {
565  pifanub = 6;
566  pifamode = PSD_FLIP_ANGLE_MODE_EXCITE;
567  cvdef(opflip, 10);
568  pifaval2 = 10;
569  pifaval3 = 15;
570  pifaval4 = 20;
571  pifaval5 = 30;
572  pifaval6 = 90;
573  }
574  opflip = _opflip.defval;
575 
576 
577  /* slice thickness */
578  pistnub = 5;
579  if (!KS_3D_SELECTED) {
580  cvdef(opslthick, 4);
581  pistval2 = 3;
582  pistval3 = 4;
583  pistval4 = 5;
584  pistval5 = 6;
585  pistval6 = 10;
586  } else {
587  cvdef(opslthick, 2);
588  pistval2 = 1.50;
589  pistval3 = 1.75;
590  pistval4 = 2.00;
591  pistval5 = 2.25;
592  pistval6 = 2.50;
593  }
594  opslthick = _opslthick.defval;
595 
596  /* slice spacing */
597  cvdef(opslspace, 0);
598  opslspace = _opslspace.defval;
599  piisil = PSD_ON;
600  if (!KS_3D_SELECTED) {
601  piisnub = 4;
602  piisval2 = 0;
603  piisval3 = 0.5;
604  piisval4 = 1;
605  piisval5 = 4;
606  piisval6 = 20;
607  } else { /* change these to do overlaps */
608  piisnub = 0;
609  piisval2 = 0;
610  }
611 
612  /* default # of slices */
613  cvdef(opslquant, 30);
614 
615  /* 3D slice settings */
616  if (KS_3D_SELECTED) {/* PSD_3D (=2) or PSD_3DM (=6) */
617 
618  if (opimode == PSD_3DM) {
619  return ks_error("ksepi: 3D multislab mode not supported");
620  }
621 
622  if (acq_type == TYPSPIN) {
623  return ks_error("ksepi: 3D spin echo epi not supported");
624  }
625 
626  pimultislab = 0; /* 0: forces only single slab, 1: allow multi-slab */
627  pilocnub = 4;
628  pilocval2 = 32;
629  pilocval3 = 64;
630  pilocval4 = 128;
631  /* opslquant = #slices in slab. opvquant = #slabs */
632  cvdef(opslquant, 32);
633  }
634 
635  /* Multi phase (i.e. multi volumes) */
636  if (opmph) {
637  pimphscrn = 1; /* display Multi-Phase Parameter screen */
638  pifphasenub = 6;
639  pifphaseval2 = 10;
640  pifphaseval3 = 20;
641  pifphaseval4 = 50;
642  pifphaseval5 = 100;
643  pifphaseval6 = 200;
644  pisldelnub = 0;
645  /*
646  pisldelval3 = 1s;
647  pisldelval4 = 2s;
648  pisldelval5 = 5s;
649  pisldelval6 = 10s;
650  */
651  piacqnub = 0;
652  setexist(opacqo, 1);
653  pihrepnub = 0; /* no XRR gating */
654  } else {
655  if (!opdiffuse) {
656  cvoverride(opfphases, 1, PSD_FIX_OFF, PSD_EXIST_OFF);
657  }
658  pimphscrn = 0; /* do not display the Multi-Phase Parameter screen */
659  }
660 
661 
662  /* Prescan buttons (autoshim). c.f. epic.h */
663  pipscoptnub = 1; /* Bit map of number of Prescan option buttons. 0=none, 1=autoshim, 2=phase corr */
664 
665  /* opuser0: show GIT revision (GITSHA) using REV variable from the Imakefile */
666 #ifdef REV
667  char userstr[100];
668  sprintf(userstr, "PSD version: %s", REV);
669  cvmod(opuser0, 0, 0, 0, userstr, 0, " ");
670  piuset |= use0;
671 #endif
672 
673  /* opuser1: Number of overscans (extra kylines) for partial Fourier */
674  cvmod(opuser1, _ksepi_kynover.minval, _ksepi_kynover.maxval, _ksepi_kynover.defval, _ksepi_kynover.descr, 0, " ");
675  opuser1 = _ksepi_kynover.defval;
676  piuset |= use1;
677 
678  cvmod(opuser2, _ksepi_blipsign.minval, _ksepi_blipsign.maxval, _ksepi_blipsign.defval, _ksepi_blipsign.descr, 0, " ");
679  opuser2 = _ksepi_blipsign.defval;
680  piuset |= use2;
681 
682 
683 
684  /* enum {KSEPI_MULTISHOT_OFF=0,KSEPI_MULTISHOT_ALLVOLS=1,KESPI_MULTISHOT_1STVOL=2, KSEPI_MULTISHOT_B0VOLS=3 */
685  if (KS_3D_SELECTED) {
686  piuset &= ~use5;
687  cvdef(ksepi_multishot_control, 0);
688  } else {
689  piuset |= use5;
690  if (opdiffuse) {
691  cvdef(ksepi_multishot_control, 3);
692  cvdesc(ksepi_multishot_control, "0:PI 1:All MulShot 2:1stMulShot 3:b0MulShot");
693  } else {
694  cvdef(ksepi_multishot_control, 2);
695  cvdesc(ksepi_multishot_control, "0:PI 1:All MulShot 2:1stMulShot");
696  }
697  }
698  cvmod(opuser5, _ksepi_multishot_control.minval, _ksepi_multishot_control.maxval, _ksepi_multishot_control.defval, _ksepi_multishot_control.descr, 0, " ");
699  opuser5 = (float) _ksepi_multishot_control.defval;
700 
701  /* OFFLINE_DIFFRETURN_ALL = 0, OFFLINE_DIFFRETURN_ACQUIRED = 1, OFFLINE_DIFFRETURN_B0 = 2, OFFLINE_DIFFRETURN_MEANDWI = 4, OFFLINE_DIFFRETURN_MEANADC = 8, OFFLINE_DIFFRETURN_EXPATT = 16, OFFLINE_DIFFRETURN_FA = 32, OFFLINE_DIFFRETURN_CFA = 64; */
702  cvmod(opuser6, _ksepi_diffusion_returnmode.minval, _ksepi_diffusion_returnmode.maxval, _ksepi_diffusion_returnmode.defval, _ksepi_diffusion_returnmode.descr, 0, " ");
703  opuser6 = (float) _ksepi_diffusion_returnmode.defval;
704  if (opdiffuse) {
705  piuset |= use6;
706  } else {
707  piuset &= ~use6;
708  }
709 
710  cvmod(opuser7, _ksepi_swi_returnmode.minval, _ksepi_swi_returnmode.maxval, _ksepi_swi_returnmode.defval, _ksepi_swi_returnmode.descr, 0, " ");
711  opuser7 = (float) _ksepi_swi_returnmode.defval;
712  if (oppseq != PSD_SE) { /* show for GE variants (PSD_GE, PSD_SPGR, ...) */
713  piuset |= use7;
714  } else {
715  piuset &= ~use7;
716  cvoverride(ksepi_swi_returnmode, 0, PSD_FIX_OFF, PSD_EXIST_OFF);
717  }
718 
719  /* make FLEET volume for GRAPPA calibration */
720  _ksepi_fleet.defval = !KS_3D_SELECTED; /* Default off for 3D */
721  cvmod(opuser8, _ksepi_fleet.minval, _ksepi_fleet.maxval, _ksepi_fleet.defval, _ksepi_fleet.descr, 0, " ");
722  opuser8 = (float) _ksepi_fleet.defval;
723  piuset |= use8;
724 
725  /* Number of phase reference lines for ghost correction per shot */
726  cvdef(ksepi_reflines, 0);
727  ksepi_reflines = _ksepi_reflines.defval;
728 
729  cvmod(opuser9, _ksepi_reflines.minval, _ksepi_reflines.maxval, _ksepi_reflines.defval, _ksepi_reflines.descr, 0, " ");
730  opuser9 = (float) _ksepi_reflines.defval;
731  piuset |= use9;
732 
733  if (KS_3D_SELECTED) {
734  piuset |= use12;
735  cvdef(ksepi_rf3Dopt, 1);
736  } else {
737  piuset &= ~use12;
738  cvdef(ksepi_rf3Dopt, 0);
739  }
740  ksepi_rf3Dopt = _ksepi_rf3Dopt.defval;
741  cvmod(opuser12, _ksepi_rf3Dopt.minval, _ksepi_rf3Dopt.maxval, _ksepi_rf3Dopt.defval, "Choose 3D RF", 0, " ");
742  opuser12 = (float) _ksepi_rf3Dopt.defval;
743 
744  if (KS_3D_SELECTED) {
745  cvmod(opuser15, _ksepi_kz_nacslines.minval, _ksepi_kz_nacslines.maxval, _ksepi_kz_nacslines.defval, _ksepi_kz_nacslines.descr, 0, " ");
746  opuser15 = (int) _ksepi_kz_nacslines.defval;
747  piuset |= use15;
748  } else {
749  piuset &= ~use15;
750  }
751 
752  /*
753  Reserved opusers:
754  -----------------
755  ksepi_diffusion_predownload_setrecon(): opuser20-25 (needed by GE's recon)
756  ksepi_eval_inversion(): opuser26-29
757  GE reserves: opuser36-48 (epic.h)
758  */
759 
760 
761  /* Acceleration menu (max accel = 4). But we don't show ARC for 2D */
763 
764  /* multi-shot button (see also ksepi_eval_UI()) */
765  if (opdiffuse) {
766  pishotnub = 0;
767  } else {
768  pishotnub = 63;
769  }
770  if (KS_3D_SELECTED) {
771  pishotval2 = 8;
772  pishotval3 = 12;
773  pishotval4 = 16;
774  pishotval5 = 24;
775  pishotval6 = 32;
776  cvdef(opnshots, 16);
777 } else {
778  pishotval2 = 1;
779  pishotval3 = 2;
780  pishotval4 = 4;
781  pishotval5 = 8;
782  pishotval6 = 16;
783  cvdef(opnshots, 1);
784  }
785  cvmin(opnshots, 1);
786  cvmax(opnshots, 512);
787  opnshots = _opnshots.defval;
788 
789  /* Make R/L freq encoding attempts (a la epi2.e) */
790  if ((TX_COIL_LOCAL == getTxCoilType() && (exist(opplane) == PSD_AXIAL || exist(opplane)== PSD_COR) ) ||
791  (TX_COIL_LOCAL == getTxCoilType() && exist(opplane) == PSD_OBL && existcv(opplane) && (exist(opobplane) == PSD_AXIAL || exist(opobplane) == PSD_COR) )) {
792  piswapfc = 1;
793  } else {
794  piswapfc = 0;
795  }
796 
797 
798 
799  /* Diffusion init */
800  status = ksepi_diffusion_init_UI();
801  if (status != SUCCESS) return status;
802 
803  return SUCCESS;
804 
805 } /* ksepi_init_UI() */
Definition: KSFoundation.h:1950
int opxres
int opyres
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
#define KSEPI_MAXRBW_NORAMPSAMPLING
Definition: ksepi_implementation.e:36
float ksepi_kissoff_factor
Definition: ksepi_implementation.e:114
float opfov
int ksepi_rf3Dopt
Definition: ksepi_implementation.e:113
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
STATUS ksepi_diffusion_init_UI()
Definition: ksepi_implementation_diffusion.e:181
int ksepi_swi_returnmode
Definition: ksepi_implementation.e:167
int ksepi_reflines
Definition: ksepi_implementation.e:162
float opslthick
int ksepi_multishot_control
Definition: ksepi_implementation.e:180
int ksepi_rampsampling
Definition: ksepi_implementation.e:124

◆ ksepi_eval_UI()

STATUS ksepi_eval_UI ( )

Gets the current UI and checks for valid inputs

Return values
STATUSSUCCESS or FAILURE
829  {
830  STATUS status;
831 
832  if (ksepi_init_UI() == FAILURE)
833  return FAILURE;
834 
835  /*** Copy UserCVs to human readable CVs ***/
836  if (existcv(opautote) && opautote == PSD_MINTE) {
837  ksepi_kynover = (int) opuser1;
838  if (ksepi_kynover < _ksepi_kynover.minval || ksepi_kynover > _ksepi_kynover.maxval)
839  return ks_error("'#extralines for minTE' is out of range");
840  }
841 
842  ksepi_blipsign = (int) opuser2;
844  return ks_error("The EPI blip sign must be either +1 or -1"); /* User error */
845  }
846 
847  /* ksepi_ky_R = 1 means that k-space is fully sampled over opnshots TR
848  ksepi_ky_R = opnshots means that k-space is sampled once with undersampling factor of opnshots
849  See also ksepi_pg()->ks_phaseencoding_generate_epi() where multiple phase encoding plans are set up. */
850 
851  cvoverride(ksepi_ky_R, (oparc) ? ((int) opaccel_ph_stride) : 1, PSD_FIX_ON, PSD_EXIST_ON);
852 
853  if (opdiffuse) {
854  cvoverride(opnshots, ksepi_ky_R, PSD_FIX_ON, PSD_EXIST_ON); /* Shots and undersampling must be the same for diffusion */
855  }
856 
857  if (existcv(opnshots) && (opnshots > 1 && (opnshots % ksepi_ky_R != 0))) {
858  return ks_error("R must be an integer factor of opnshots"); /* User error */
859  }
860 
861  /* Reserved opusers:
862  -----------------
863  ksepi_diffusion_predownload_setrecon(): opuser20-25 (needed by GE's recon)
864  ksepi_eval_inversion(): opuser26-29
865  GE reserves: opuser36-48 (epic.h)
866  */
867 
868  /* Multi-shot */
869 
870  ksepi_multishot_control = (int) (KS_3D_SELECTED) ? 0 : opuser5;
871  if (ksepi_multishot_control < _ksepi_multishot_control.minval || ksepi_multishot_control > _ksepi_multishot_control.maxval) {
872  return ks_error("multishot control (CV5) must be in range [%d,%d]", _ksepi_multishot_control.minval, _ksepi_multishot_control.maxval);
873  }
874  cvoverride(opasset, FALSE, _opasset.fixedflag, _opasset.existflag); /* force asset off, but keep exist/fixed status */
875  piechnub = 63;
876 
877  ksepi_diffusion_returnmode = (int) opuser6;
878 
879  /* Don't do the extra ghost correction volume (integrated refscan) if ETL = 1 */
880  if (ksepi.epitrain.etl == 1) {
881  ksepi_ghostcorr = FALSE;
882  } else {
883  ksepi_ghostcorr = TRUE;
884  }
885 
886  /* Diffusion eval */
887  status = ksepi_diffusion_eval_UI();
888  if (status != SUCCESS) return status;
889 
890  ksepi_swi_returnmode = (int) opuser7;
891 
892  ksepi_fleet = (int) opuser8;
893  ksepi_reflines = (int) opuser9;
894 
895  ksepi_rf3Dopt = (int) opuser12;
896 
897  ksepi_kz_nacslines = (int) opuser15;
898 
899  return SUCCESS;
900 
901 } /* ksepi_eval_UI() */
int ksepi_diffusion_returnmode
Definition: ksepi_implementation_diffusion.e:66
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
int ksepi_ky_R
Definition: ksepi_implementation.e:139
KS_EPI epitrain
Definition: ksepi_implementation.e:50
STATUS ksepi_diffusion_eval_UI()
Definition: ksepi_implementation_diffusion.e:315
int etl
Definition: KSFoundation.h:1843
int ksepi_kz_nacslines
Definition: ksepi_implementation.e:141
Definition: KSFoundation.h:1929
int ksepi_rf3Dopt
Definition: ksepi_implementation.e:113
int ksepi_blipsign
Definition: ksepi_implementation.e:135
int ksepi_swi_returnmode
Definition: ksepi_implementation.e:167
int ksepi_kynover
Definition: ksepi_implementation.e:137
int ksepi_reflines
Definition: ksepi_implementation.e:162
STATUS ksepi_init_UI(void)
Initial setup of user interface (UI) with default values for menus and fields
Definition: ksepi_implementation.e:368
int ksepi_ghostcorr
Definition: ksepi_implementation.e:178
int ksepi_fleet
Definition: ksepi_implementation.e:153
int ksepi_multishot_control
Definition: ksepi_implementation.e:180
Definition: KSFoundation.h:1929

◆ ksepi_eval_setuprf_3dexc()

STATUS ksepi_eval_setuprf_3dexc ( KS_SELRF selrfexc,
int  rf3Dopt 
)
956  {
957 
958 
959  selrfexc->rf = spsp_ss30260334; /* 3T SPSP */
960  selrfexc->gradwave = spsp_ss30260334_gz; /* normalized to 1 G/cm */
961 
962  if (rf3Dopt > 0) {
963 
964  if (exist(opslquant) * exist(opslthick) >= 150) {
965 
966  /* 150 mm pulses goes here */
967 
968  switch (rf3Dopt) {
969 
970  case 1:
971  selrfexc->rf = exc_SPSP3D_150mm_stbw10_etbw4_lin_lin; /* 3T SPSP */
972  selrfexc->gradwave = exc_SPSP3D_150mm_stbw10_etbw4_lin_lin_gz; /* normalized to 1 G/cm */
973  break;
974 
975  case 2:
976  selrfexc->rf = exc_SPSP3D_150mm_stbw10_etbw4_lin_min; /* 3T SPSP */
977  selrfexc->gradwave = exc_SPSP3D_150mm_stbw10_etbw4_lin_min_gz; /* normalized to 1 G/cm */
978  break;
979 
980  case 3:
981  selrfexc->rf = exc_SPSP3D_150mm_stbw10_etbw5_lin_min; /* 3T SPSP */
982  selrfexc->gradwave = exc_SPSP3D_150mm_stbw10_etbw5_lin_min_gz; /* normalized to 1 G/cm */
983  break;
984 
985  case 4:
986  selrfexc->rf = exc_SPSP3D_150mm_stbw10_etbw4_min_min; /* 3T SPSP */
987  selrfexc->gradwave = exc_SPSP3D_150mm_stbw10_etbw4_min_min_gz; /* normalized to 1 G/cm */
988  break;
989 
990  case 5:
991  selrfexc->rf = exc_SPSP3D_150mm_stbw10_etbw5_min_min; /* 3T SPSP */
992  selrfexc->gradwave = exc_SPSP3D_150mm_stbw10_etbw5_min_min_gz; /* normalized to 1 G/cm */
993  break;
994 
995  case 6:
996  selrfexc->rf = exc_SPSP3D_150mm_stbw10_etbw6_min_min; /* 3T SPSP */
997  selrfexc->gradwave = exc_SPSP3D_150mm_stbw10_etbw6_min_min_gz; /* normalized to 1 G/cm */
998  break;
999 
1000  case 7:
1001  selrfexc->rf = exc_SPSP3D_150mm_stbw10_etbw4_max_max; /* 3T SPSP */
1002  selrfexc->gradwave = exc_SPSP3D_150mm_stbw10_etbw4_max_max_gz; /* normalized to 1 G/cm */
1003  break;
1004 
1005  case 8:
1006  selrfexc->rf = exc_SPSP3D_150mm_stbw10_etbw5_max_max; /* 3T SPSP */
1007  selrfexc->gradwave = exc_SPSP3D_150mm_stbw10_etbw5_max_max_gz; /* normalized to 1 G/cm */
1008  break;
1009 
1010  default:
1011  return ks_error("%s: ksepi_rf3Dopt = %d is out of range", __FUNCTION__, ksepi_rf3Dopt);
1012  break;
1013  }
1014 
1015  } else if (exist(opslquant) * exist(opslthick) >= 40) {
1016 
1017  /* 40 mm pulses goes here */
1018  switch(rf3Dopt) {
1019 
1020  case 1:
1021  selrfexc->rf = exc_SPSP3D_40mm_stbw4_etbw5_min_min; /* 3T SPSP */
1022  selrfexc->gradwave = exc_SPSP3D_40mm_stbw4_etbw5_min_min_gz; /* normalized to 1 G/cm */
1023  break;
1024 
1025  case 2:
1026  selrfexc->rf = exc_SPSP3D_40mm_stbw4_etbw6_min_min; /* 3T SPSP */
1027  selrfexc->gradwave = exc_SPSP3D_40mm_stbw4_etbw6_min_min_gz; /* normalized to 1 G/cm */
1028  break;
1029 
1030  default: /* same as case 2 for now. Don't want to throw an error when slab is lower than 150 mm and rf3Dopt > 2 */
1031  selrfexc->rf = exc_SPSP3D_40mm_stbw4_etbw6_min_min; /* 3T SPSP */
1032  selrfexc->gradwave = exc_SPSP3D_40mm_stbw4_etbw6_min_min_gz; /* normalized to 1 G/cm */
1033  break;
1034  }
1035 
1036  } /* >= 40 mm */
1037 
1038  } /* rf3Dopt > 0 */
1039 
1040  char tmpstr[KS_DESCRIPTION_LENGTH+20];
1041  sprintf(tmpstr, "Choose 3D RF [%s]", selrfexc->rf.designinfo);
1042  cvdesc(opuser12, tmpstr);
1043 
1044  return SUCCESS;
1045 }
DECL_TYPE KS_RF exc_SPSP3D_150mm_stbw10_etbw5_max_max
Definition: KSFoundation_KSRF.c:96
KS_DESCRIPTION designinfo
Definition: KSFoundation.h:947
DECL_TYPE KS_RF exc_SPSP3D_150mm_stbw10_etbw4_lin_min
Definition: KSFoundation_KSRF.c:66
DECL_TYPE KS_WAVE exc_SPSP3D_150mm_stbw10_etbw4_lin_lin_gz
Definition: KSFoundation_KSRF.c:63
DECL_TYPE KS_RF spsp_ss30260334
Definition: KSFoundation_GERF.c:136
KS_WAVE gradwave
Definition: KSFoundation.h:1493
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
DECL_TYPE KS_RF exc_SPSP3D_150mm_stbw10_etbw6_min_min
Definition: KSFoundation_KSRF.c:86
DECL_TYPE KS_WAVE exc_SPSP3D_150mm_stbw10_etbw4_min_min_gz
Definition: KSFoundation_KSRF.c:78
DECL_TYPE KS_WAVE exc_SPSP3D_40mm_stbw4_etbw5_min_min_gz
Definition: KSFoundation_KSRF.c:103
DECL_TYPE KS_RF exc_SPSP3D_40mm_stbw4_etbw5_min_min
Definition: KSFoundation_KSRF.c:101
#define KS_DESCRIPTION_LENGTH
Definition: KSFoundation.h:185
DECL_TYPE KS_WAVE exc_SPSP3D_150mm_stbw10_etbw5_max_max_gz
Definition: KSFoundation_KSRF.c:98
DECL_TYPE KS_WAVE spsp_ss30260334_gz
Definition: KSFoundation_GERF.c:138
KS_RF rf
Definition: KSFoundation.h:1485
DECL_TYPE KS_RF exc_SPSP3D_40mm_stbw4_etbw6_min_min
Definition: KSFoundation_KSRF.c:106
DECL_TYPE KS_WAVE exc_SPSP3D_150mm_stbw10_etbw5_lin_min_gz
Definition: KSFoundation_KSRF.c:73
DECL_TYPE KS_WAVE exc_SPSP3D_150mm_stbw10_etbw6_min_min_gz
Definition: KSFoundation_KSRF.c:88
int ksepi_rf3Dopt
Definition: ksepi_implementation.e:113
DECL_TYPE KS_RF exc_SPSP3D_150mm_stbw10_etbw5_min_min
Definition: KSFoundation_KSRF.c:81
DECL_TYPE KS_WAVE exc_SPSP3D_150mm_stbw10_etbw4_lin_min_gz
Definition: KSFoundation_KSRF.c:68
DECL_TYPE KS_WAVE exc_SPSP3D_150mm_stbw10_etbw4_max_max_gz
Definition: KSFoundation_KSRF.c:93
DECL_TYPE KS_RF exc_SPSP3D_150mm_stbw10_etbw5_lin_min
Definition: KSFoundation_KSRF.c:71
DECL_TYPE KS_WAVE exc_SPSP3D_40mm_stbw4_etbw6_min_min_gz
Definition: KSFoundation_KSRF.c:108
DECL_TYPE KS_RF exc_SPSP3D_150mm_stbw10_etbw4_max_max
Definition: KSFoundation_KSRF.c:91
float opslthick
DECL_TYPE KS_WAVE exc_SPSP3D_150mm_stbw10_etbw5_min_min_gz
Definition: KSFoundation_KSRF.c:83
DECL_TYPE KS_RF exc_SPSP3D_150mm_stbw10_etbw4_min_min
Definition: KSFoundation_KSRF.c:76
DECL_TYPE KS_RF exc_SPSP3D_150mm_stbw10_etbw4_lin_lin
Definition: KSFoundation_KSRF.c:61

◆ ksepi_eval_setuprf()

STATUS ksepi_eval_setuprf ( )
1048  {
1049 
1050  /* selective RF excitation */
1051  if (opfat || ksepi_fse90 == TRUE) {
1052  ksepi.selrfexc.rf = exc_fse90; /* KSFoundation_GERF.h */
1053  ks_init_wave(&ksepi.selrfexc.gradwave); /* clear gradwave */
1054  } else {
1055  if (cffield == 30000) {
1056  if (KS_3D_SELECTED) {
1058  return FAILURE;
1059  } else {
1060  /* In 2D always use the standard GE pulse */
1061  ksepi.selrfexc.rf = spsp_ss30260334; /* 3T SPSP */
1062  ksepi.selrfexc.gradwave = spsp_ss30260334_gz; /* normalized to 1 G/cm */
1063  }
1064  } else {
1065  ksepi.selrfexc.rf = spsp_ss1528822; /* 1.5T SPSP */
1066  ksepi.selrfexc.gradwave = spsp_ss1528822_gz; /* normalized to 1 G/cm */
1067  }
1068  } /* RF Excitation */
1069 
1070  if (acq_type == TYPSPIN)
1071  ksepi.selrfexc.rf.flip = 90.0; /* always 90 FA for SE-EPI */
1072  else
1073  ksepi.selrfexc.rf.flip = opflip; /* variable FA for GE-EPI */
1074 
1075  if (KS_3D_SELECTED) {
1076  cvoverride(opvthick, exist(opslquant) * exist(opslthick), _opslquant.fixedflag, existcv(opslquant));
1077  ksepi_excthickness = (exist(opslquant) - 2 * pislblank) * exist(opslthick);
1078  } else {
1080  }
1081 
1082  /* Don't oversize slices for 3D */
1083  ksepi_gscalerfexc = (KS_3D_SELECTED) ? 1.0 : 0.9;
1084  ksepi_gscalerfref = (KS_3D_SELECTED) ? 1.0 : 0.9;
1085 
1087 
1088 
1089  if (ks_eval_selrf1p(&ksepi.selrfexc, "rfexc") == FAILURE) {
1090  if (opfat || opslthick >= 3.0) {
1091  return FAILURE;
1092  } else {
1093  /* override the error message from ks_eval_selrf1p() for SPSP and thin slices, to guide the operator to run the sequence
1094  with a fat sat pulse and a regular 90 pulse */
1095  return ks_error("ks_eval_selrf1p(rfexc): Too small slice thickness. Try FatSat pulse");
1096  }
1097  }
1098 
1099 
1100  /* selective RF refocusing */
1101  if (acq_type == TYPSPIN) {
1103  ksepi.selrfref.rf.flip = opflip; /* since pifamode = PSD_FLIP_ANGLE_MODE_REFOCUS when TYPSPIN */
1106 
1107  if (ks_eval_selrf1p(&ksepi.selrfref, "rfref") == FAILURE)
1108  return FAILURE;
1109  } else {
1110  ks_init_selrf(&ksepi.selrfref); /* GE-EPI: reset to default values (incl. zero .duration) */
1111  }
1112 
1113  /* selective RF refocusing with diffusion and opdualspinecho */
1114  if (acq_type == TYPSPIN && opdiffuse && opdualspinecho) {
1116  ksepi.selrfref2.rf.flip = opflip; /* since pifamode = PSD_FLIP_ANGLE_MODE_REFOCUS when TYPSPIN */
1118  ksepi.selrfref2.crusherscale = ksepi_crusherscale * ksepi_diffusion_2ndcrushfact; /* ksepi_diffusion_2ndcrushfact times bigger crushers to avoid stimulated echoes */
1119 
1120  if (ks_eval_selrf1p(&ksepi.selrfref2, "rfref2") == FAILURE)
1121  return FAILURE;
1122  } else {
1123  ks_init_selrf(&ksepi.selrfref2); /* Not opdualspinecho diffusion: reset to default values (incl. zero .duration) */
1124  }
1125 
1126  return SUCCESS;
1127 
1128 } /* ksepi_eval_setuprf() */
DECL_TYPE KS_WAVE spsp_ss1528822_gz
Definition: KSFoundation_GERF.c:133
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
float ksepi_gscalerfref
Definition: ksepi_implementation.e:119
KS_SELRF selrfexc
Definition: ksepi_implementation.e:53
DECL_TYPE KS_RF spsp_ss30260334
Definition: KSFoundation_GERF.c:136
KS_WAVE gradwave
Definition: KSFoundation.h:1493
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
float ksepi_excthickness
Definition: ksepi_implementation.e:107
float ksepi_crusherscale
Definition: ksepi_implementation.e:118
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
float ksepi_diffusion_2ndcrushfact
Definition: ksepi_implementation_diffusion.e:65
float flip
Definition: KSFoundation.h:940
DECL_TYPE KS_WAVE spsp_ss30260334_gz
Definition: KSFoundation_GERF.c:138
KS_RF rf
Definition: KSFoundation.h:1485
KS_SELRF selrfref
Definition: ksepi_implementation.e:54
DECL_TYPE KS_RF exc_fse90
Definition: KSFoundation_GERF.c:62
STATUS ksepi_eval_setuprf_3dexc(KS_SELRF *selrfexc, int rf3Dopt)
Definition: ksepi_implementation.e:956
int ksepi_rf3Dopt
Definition: ksepi_implementation.e:113
void ks_init_selrf(KS_SELRF *selrf)
Resets a KS_SELRF sequence object to its default value (KS_INIT_SELRF)
Definition: KSFoundation_host.c:78
DECL_TYPE KS_RF spsp_ss1528822
Definition: KSFoundation_GERF.c:131
DECL_TYPE KS_RF ref_se1b4
Definition: KSFoundation_GERF.c:104
float crusherscale
Definition: KSFoundation.h:1488
KS_SELRF selrfref2
Definition: ksepi_implementation.e:55
float ksepi_gscalerfexc
Definition: ksepi_implementation.e:108
float opslthick
void ks_init_wave(KS_WAVE *wave)
Resets a KS_WAVE sequence object to its default value (KS_INIT_WAVE)
Definition: KSFoundation_host.c:66
int ksepi_fse90
Definition: ksepi_implementation.e:112
float slthick
Definition: KSFoundation.h:1487

◆ ksepi_eval_setupfleet()

STATUS ksepi_eval_setupfleet ( )
1131  {
1132 
1135  if (ks_eval_selrf1p(&ksepi_fleetseq.selrfexc, "fleetrfexc") == FAILURE)
1136  return FAILURE;
1137 
1138  /* echo time shifting */
1141  if (ksepi_echotime_shifting == TRUE) {
1142  /*** Set up a pair of wait objects that are used to shift back the RF up to the echospacing ***/
1143  if (ks_eval_wait(&ksepi_fleetseq.pre_delay,"ksepi_fleet_wait_pre", GRAD_UPDATE_TIME) == FAILURE) {
1144  return FAILURE;
1145  }
1146  if (ks_eval_wait(&ksepi_fleetseq.post_delay,"ksepi_fleet_wait_post", ksepi_echotime_shifting_sumdelay - GRAD_UPDATE_TIME) == FAILURE) {
1147  return FAILURE;
1148  }
1149  }
1150 
1153  RUP_FACTOR((int) ksepi_fleet_num_ky, 2), /* round up (RUP) to nearest multiple of 2 */
1155  ksepi_fleetseq.epitrain.blipphaser.nover = 0; /* no partial Fourier for FLEET */
1156 
1157  if (KS_3D_SELECTED) { /* PSD_3D or PSD_3DM */
1158  ksepi_fleetseq.epitrain.zphaser.res = IMax(2, 1, IMin(2, ksepi_fleet_num_kz, opslquant));
1159  } else {
1161  }
1162 
1163  if (ks_eval_epi(&ksepi_fleetseq.epitrain, "epifleet", ks_qfact) == FAILURE)
1164  return FAILURE;
1165 
1167  if (ks_eval_trap(&ksepi_fleetseq.spoiler, "fleetspoiler") == FAILURE)
1168  return FAILURE;
1169 
1171  strcpy(ksepi_fleetseq.seqctrl.description, "ksepifleet");
1172 
1173  return SUCCESS;
1174 }
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:76
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
int res
Definition: KSFoundation.h:1678
KS_SELRF selrfexc
Definition: ksepi_implementation.e:53
#define KS_NOTSET
Definition: KSFoundation.h:103
int ksepi_echotime_shifting
Definition: ksepi_implementation.e:136
KS_WAIT pre_delay
Definition: ksepi_implementation.e:80
float ksepi_fleet_flip
Definition: ksepi_implementation.e:154
KS_PHASER blipphaser
Definition: KSFoundation.h:1840
float ksepi_spoilerarea
Definition: ksepi_implementation.e:110
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:201
KS_PHASER zphaser
Definition: KSFoundation.h:1841
float flip
Definition: KSFoundation.h:940
KS_EPI epitrain
Definition: ksepi_implementation.e:50
float ks_qfact
Definition: GERequired.e:243
void ks_init_wait(KS_WAIT *wait)
Resets a KS_WAIT sequence object to its default value (KS_INIT_WAIT)
Definition: KSFoundation_host.c:62
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
KS_TRAP spoiler
Definition: ksepi_implementation.e:78
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
float area
Definition: KSFoundation.h:582
KS_WAIT post_delay
Definition: ksepi_implementation.e:81
STATUS ks_eval_wait(KS_WAIT *wait, const char *const desc, int maxduration) WARN_UNUSED_RESULT
Sets up a wait pulse using a KS_WAIT sequence object
Definition: KSFoundation_host.c:219
int nover
Definition: KSFoundation.h:1679
int ksepi_echotime_shifting_sumdelay
Definition: ksepi_implementation.e:210
KS_DESCRIPTION description
Definition: KSFoundation.h:1141
int ksepi_fleet_num_kz
Definition: ksepi_implementation.e:157
KS_SELRF selrfexc
Definition: ksepi_implementation.e:79
STATUS ks_eval_epi(KS_EPI *epi, const char *const desc, float quietnessfactor) WARN_UNUSED_RESULT
Sets up a KS_EPI composite sequence object with preset gradient constraints
Definition: KSFoundation_host.c:4219
KS_EPI epitrain
Definition: ksepi_implementation.e:77
int ksepi_fleet_num_ky
Definition: ksepi_implementation.e:156

◆ ksepi_eval_setupobjects()

STATUS ksepi_eval_setupobjects ( )

Sets up all sequence objects for the main sequence module (KSEPI_SEQUENCE ksepi)

Return values
STATUSSUCCESS or FAILURE
1182  {
1183 
1184  /* All RF related setup in separate function */
1185  if (ksepi_eval_setuprf() == FAILURE)
1186  return FAILURE;
1187 
1188 
1189  /* EPI readout */
1191  ksepi.epitrain.read.acq.rbw = oprbw;
1193  ksepi.epitrain.read.res = RUP_FACTOR(opxres, 2); /* round up (RUP) to nearest multiple of 2 */
1195  ksepi.epitrain.read.nover = 0; /* never partial Fourier in kx for EPI */
1196 
1197  ksepi.epitrain.blipphaser.fov = opfov * opphasefov;
1198  ksepi.epitrain.blipphaser.res = RUP_FACTOR((int) (opyres * opphasefov), 2); /* round up (RUP) to nearest multiple of 2 */
1199 
1200  /* upsample to nearest power of 2 for res up to 256. For higher matrix sizes, use native res
1201  KSFoundation.h: {KS_IMSIZE_NATIVE, KS_IMSIZE_POW2, KS_IMSIZE_MIN256} */
1202  if (ksepi.epitrain.read.res < 256 && ksepi.epitrain.blipphaser.res < 256) {
1204  } else {
1206  }
1207 
1208  if (opautote == PSD_MINTE) /* partial Fourier in ky */
1210  else
1212 
1213  if (opasset == ASSET_SCAN) {
1214  /* ASSET acceleration, without acs lines (since 2nd arg = 0) */
1215  if (ks_eval_phaser_setaccel(&ksepi.epitrain.blipphaser, 0, opaccel_ph_stride) == FAILURE)
1216  return FAILURE;
1217  } else {
1218  /* R is used as multishot if not ASSET has been selected */
1219  ksepi.epitrain.blipphaser.R = opnshots; /* using multi-shot to accelerate EPI readout */
1220  ksepi.epitrain.blipphaser.nacslines = 0; /* never have acs lines for EPI */
1221  }
1222 
1223  /* z phase encoding gradient for the 3D case (one zphase enc. per TR, not real 3D EPI) */
1224  if (KS_3D_SELECTED) { /* PSD_3D or PSD_3DM */
1225  ksepi_kz_R = opaccel_sl_stride;
1226  ksepi.epitrain.zphaser.fov = opvthick;
1227  ksepi.epitrain.zphaser.res = IMax(2, 1, opslquant);
1231  } else {
1232  ksepi.epitrain.zphaser.res = KS_NOTSET; /* ks_eval_epi will clear zphaser if res <= 1 */
1233  }
1234 
1235  if (ks_eval_epi(&ksepi.epitrain, "epi", ksepi_epiqfact) == FAILURE) {
1236  return FAILURE;
1237  }
1238 
1239  /* echo time shifting */
1242 
1243  if (ksepi_echotime_shifting == TRUE) {
1244  /*** Set up a pair of wait objects that are used to shift back the RF up to the echospacing ***/
1247  if (ks_eval_wait(&ksepi.pre_delay,"ksepi_wait_pre", GRAD_UPDATE_TIME) == FAILURE) {
1248  return FAILURE;
1249  }
1250  if (ks_eval_wait(&ksepi.post_delay,"ksepi_wait_post", ksepi_echotime_shifting_sumdelay - GRAD_UPDATE_TIME) == FAILURE) {
1251  return FAILURE;
1252  }
1253  }
1254 
1255  if (ksepi_reflines > 0) {
1259 
1260  ksepi.dynreftrain.zphaser.res = KS_NOTSET; /* disable zphaser for reflines */
1261 
1262  if (ks_eval_epi(&ksepi.dynreftrain, "epireflines", ks_qfact) == FAILURE) {
1263  return FAILURE;
1264  }
1265  ks_init_phaser(&ksepi.dynreftrain.blipphaser); /* disable blipphaser for reflines */
1266  ks_init_trap(&ksepi.dynreftrain.blip); /* disable blips for reflines */
1267  }
1268  else {
1270  }
1271 
1272  /* Flow comp */
1275 
1276  if (opfcomp == TRUE) {
1277 
1278  if (ksepi_fcy) {
1279  /* Y: Need two extra phase gradients for flowcomp */
1280  if (ksepi_eval_flowcomp_phase(&ksepi.fcompphase, &ksepi.epitrain, "fcompphase") == FAILURE)
1281  return FAILURE;
1282  }
1283 
1284  if (ksepi_fcz) {
1285  /* Z: Add second z rephaser to complete 0th and 1st moment nulling of slice selection */
1287  if (ks_eval_trap(&ksepi.fcompslice, "fcompslice2") == FAILURE)
1288  return FAILURE;
1289 
1290  /* Z: Now, make normal z rephaser twice as large */
1291  ksepi.selrfexc.postgrad.area *= 2;
1292  if (ks_eval_trap(&ksepi.selrfexc.postgrad, "rfexc.reph_fc1") == FAILURE)
1293  return FAILURE;
1294  }
1295 
1296  } /* opfcomp */
1297 
1298 
1299 
1300  /* It is useful to be able to see the current echo spacing in DisplayCV to determine distortion levels etc */
1301  cvoverride(ksepi_esp, ksepi.epitrain.read.grad.duration + ksepi.epitrain.read_spacing, PSD_FIX_ON, PSD_EXIST_ON);
1302 
1303  /* for consistency, set opetl to the actual one for the EPI train even though ETL menu should never be visible for EPI */
1304  cvoverride(opetl, ksepi.epitrain.etl, PSD_FIX_ON, PSD_EXIST_ON);
1305 
1306 
1307  /* protect against too long sequence. It appears that opnecho * ksepi.epitrain.etl cannot be >= 1024 */
1308  if (ksepi.epitrain.etl * opnecho >= 1024)
1309  return ks_error("# readouts >= 1024. Please reduce echoes, phase res. or increase NumShots");
1310 
1311  /* post-read ksepi.spoiler */
1313  if (ks_eval_trap(&ksepi.spoiler, "spoiler") == FAILURE)
1314  return FAILURE;
1315 
1316  /* diffusion weighting */
1317  /* set up the diffusion gradient objects in 'ksepi'. If opdiffuse == FALSE,
1318  this function will reset the diffusion objects */
1319  if (ksepi_diffusion_eval_gradients_TE(&ksepi) == FAILURE)
1320  return FAILURE;
1321 
1322 
1323  /* init seqctrl */
1325  strcpy(ksepi.seqctrl.description, "ksepimain");
1326 
1327  /* Setup FLEET sequence */
1328  if (ksepi_eval_setupfleet() == FAILURE)
1329  return FAILURE;
1330 
1331  return SUCCESS;
1332 
1333 } /* ksepi_eval_setupobjects() */
KS_TRAP blip
Definition: KSFoundation.h:1839
int R
Definition: KSFoundation.h:1680
int res
Definition: KSFoundation.h:1678
Definition: KSFoundation.h:1948
int opxres
int ksepi_fcy
Definition: ksepi_implementation.e:147
int nacslines
Definition: KSFoundation.h:1681
KS_SELRF selrfexc
Definition: ksepi_implementation.e:53
int opyres
#define KS_NOTSET
Definition: KSFoundation.h:103
int ksepi_echotime_shifting
Definition: ksepi_implementation.e:136
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
KS_TRAP fcompphase
Definition: ksepi_implementation.e:60
float fov
Definition: KSFoundation.h:1576
KS_PHASER blipphaser
Definition: KSFoundation.h:1840
float ksepi_spoilerarea
Definition: ksepi_implementation.e:110
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
float ksepi_echotime_shifting_shotdelay
Definition: ksepi_implementation.e:207
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
KS_EPI dynreftrain
Definition: ksepi_implementation.e:51
KS_PHASER zphaser
Definition: KSFoundation.h:1841
float rbw
Definition: KSFoundation.h:734
KS_TRAP grad
Definition: KSFoundation.h:1586
int ksepi_kznover
Definition: ksepi_implementation.e:138
int ksepi_fcz
Definition: ksepi_implementation.e:148
KS_EPI epitrain
Definition: ksepi_implementation.e:50
STATUS ks_eval_phaser_setaccel(KS_PHASER *phaser, int min_acslines, float R) WARN_UNUSED_RESULT
Definition: KSFoundation_host.c:1995
float ks_qfact
Definition: GERequired.e:243
void ks_init_wait(KS_WAIT *wait)
Resets a KS_WAIT sequence object to its default value (KS_INIT_WAIT)
Definition: KSFoundation_host.c:62
int etl
Definition: KSFoundation.h:1843
int ksepi_kz_nacslines
Definition: ksepi_implementation.e:141
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:49
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
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
KS_TRAP fcompslice
Definition: ksepi_implementation.e:61
int res
Definition: KSFoundation.h:1577
KS_READTRAP read
Definition: KSFoundation.h:1837
STATUS ksepi_diffusion_eval_gradients_TE(KSEPI_SEQUENCE *ksepi)
Definition: ksepi_implementation_diffusion.e:604
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
float area
Definition: KSFoundation.h:582
int ksepi_esp
Definition: ksepi_implementation.e:130
KS_TRAP postgrad
Definition: KSFoundation.h:1492
STATUS ks_eval_wait(KS_WAIT *wait, const char *const desc, int maxduration) WARN_UNUSED_RESULT
Sets up a wait pulse using a KS_WAIT sequence object
Definition: KSFoundation_host.c:219
int nover
Definition: KSFoundation.h:1679
int ksepi_kz_R
Definition: ksepi_implementation.e:140
KS_TRAP spoiler
Definition: ksepi_implementation.e:52
int ksepi_echotime_shifting_sumdelay
Definition: ksepi_implementation.e:210
int ksepi_kynover
Definition: ksepi_implementation.e:137
STATUS ksepi_eval_setuprf()
Definition: ksepi_implementation.e:1048
int ksepi_reflines
Definition: ksepi_implementation.e:162
float ksepi_epiqfact
Definition: ksepi_implementation.e:181
KS_DESCRIPTION description
Definition: KSFoundation.h:1141
int read_spacing
Definition: KSFoundation.h:1844
int ksepi_readlobegap
Definition: ksepi_implementation.e:125
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
void ks_init_epi(KS_EPI *epi)
Resets a KS_EPI sequence object to its default value (KS_INIT_EPI)
Definition: KSFoundation_host.c:90
STATUS ksepi_eval_setupfleet()
Definition: ksepi_implementation.e:1131
int ksepi_imsize
Definition: ksepi_implementation.e:176
Definition: KSFoundation.h:1948
STATUS ks_eval_epi(KS_EPI *epi, const char *const desc, float quietnessfactor) WARN_UNUSED_RESULT
Sets up a KS_EPI composite sequence object with preset gradient constraints
Definition: KSFoundation_host.c:4219
float fov
Definition: KSFoundation.h:1677
STATUS ksepi_eval_flowcomp_phase(KS_TRAP *fcphase, const KS_EPI *epi, const char *desc)
Definition: ksepi_implementation.e:906
KS_WAIT pre_delay
Definition: ksepi_implementation.e:58
KS_WAIT post_delay
Definition: ksepi_implementation.e:59
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
int ksepi_rampsampling
Definition: ksepi_implementation.e:124

◆ ksepi_eval_TErange()

STATUS ksepi_eval_TErange ( )

Sets the min/max TE based on the durations of the sequence objects in KSEPI_SEQUENCE (ksepi)

This function handles the TE range for SE-EPI, GE-EPI and DW-EPI (opdiffuse).

Multiple EPI trains (opnecho > 1) are supported Time between the EPI readouts is controlled using ksepi_echogap, yielding a ksepi_interechotime variable used in ksepi_pg().

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 ksepi_pg(). If the pulse sequence design changes in ksepi_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
1355  {
1356  int selrfend, min90_180, min180_echo;
1357 
1358  /* RF center to RF end */
1360 
1361  if (acq_type == TYPSPIN) {
1362 
1363  /* minimum TE: Spin-Echo EPI case (also diffusion) */
1364 
1365  /*** minimum time needed between RF exc center to RF ref center ***/
1366 
1367  /* RF center to rephaser end */
1368  min90_180 = selrfend + ksepi.selrfexc.postgrad.duration;
1369  if (ksepi_slicecheck == FALSE) { /* reflines dephaser may overlap with selrf rephaser unless slicecheck mode */
1371  }
1372  min90_180 += ksepi.dynreftrain.duration; /* end of reftrain */
1373 
1374  if (opdiffuse) {
1375  min90_180 += ksepi.diffgrad.duration;
1376  } else if (ksepi_slicecheck == FALSE) {
1377  min90_180 -= IMin(2, ksepi.dynreftrain.readphaser.duration,
1378  ksepi.selrfref.pregrad.duration); /* reflines rephaser and selrefrf dephaser may overlap */
1379  }
1381 
1382  /*** minimum time needed between RF ref center and echo center (using selrfref or selrfref2 (opdualspinecho) ***/
1383  min180_echo = ksepi.diffgrad.duration; /* zero if not opdiffuse */
1384  min180_echo += ksepi.epitrain.time2center;
1385 
1386  if (ksepi_echotime_shifting == TRUE) {
1387  min180_echo += GRAD_UPDATE_TIME;
1388  }
1389 
1390  if (opdiffuse && opdualspinecho) {
1392 
1393  /* minimum TE is 4x the biggest of the two */
1394  avminte = IMax(2, min90_180, min180_echo) * 4;
1395 
1396  /* Also check that the middle two diffusion gradients (diffgrad2) fits.
1397  There should be a time corresponding to TE/2 between the two 180 pulses for opdualspinecho, and within this time two instances
1398  of ksepi.diffgrad2 must be possible to fit in (2nd and 3rd diffusion gradient) */
1399  int avail_time = (avminte/2);
1400  avail_time -= ksepi.selrfref.rf.iso2end + ksepi.selrfref.grad.ramptime + KS_RFSSP_POSTTIME + ksepi.selrfref.postgrad.duration; /* right crusher for 1st 180 */
1401  avail_time -= ksepi.selrfref2.pregrad.duration + KS_RFSSP_PRETIME + ksepi.selrfref2.grad.ramptime + ksepi.selrfref2.rf.start2iso; /* left crusher for 2nd 180 */
1402  if (ksepi.diffgrad2.duration * 2 > avail_time) {
1403  return ks_error("%s: DualSE diffusion - not enough space for 'diffgrad2'", __FUNCTION__);
1404  }
1405 
1406  } else {
1408 
1409  /* minimum TE is 2x the biggest of the two */
1410  avminte = IMax(2, min90_180, min180_echo) * 2;
1411  }
1412 
1413  } else { /* GE-EPI */
1414 
1415  avminte = selrfend;
1416 
1417  if (ksepi_reflines > 0) {
1418  /* transports between selrf and reflines readout: */
1419  if (ksepi_slicecheck) {
1421  } else {
1422  avminte += IMax(2, ksepi.dynreftrain.readphaser.duration, /* X */
1424  }
1425  /* reflines readout: */
1427  /* transports between reflines readout and main epi readout: */
1428  avminte += IMax(3, ksepi.dynreftrain.readphaser.duration + ksepi.epitrain.readphaser.duration, /* X */
1430  ksepi.epitrain.zphaser.grad.duration) /* Z */;
1431  } else { /* no reflines */
1432  /* transports between selrf and main epi readout: */
1433  if (ksepi_slicecheck) {
1434  avminte += IMax(3, ksepi.epitrain.zphaser.grad.duration, /* X */
1437  } else {
1438  avminte += IMax(3, ksepi.epitrain.readphaser.duration, /* X */
1441  }
1442  }
1443 
1444  /* start of EPI readout */
1445  avminte -= IMax(3, ksepi.epitrain.readphaser.duration, /* X */
1447  ksepi.epitrain.zphaser.grad.duration) /* Z */;
1448  /* start of EPI train */
1449  avminte += ksepi.epitrain.time2center; /* minimum TE ! */
1450 
1451  if (ksepi_echotime_shifting == TRUE) {
1452  avminte += GRAD_UPDATE_TIME;
1453  }
1454  }
1455 
1456  avminte += GRAD_UPDATE_TIME * 2; /* 8us extra margin */
1457  avminte = RUP_FACTOR(avminte, 8); /* round up to make time divisible by 8us */
1458 
1459  avmaxte = avminte; /* initialization only to avoid avmaxte = 0 */
1460 
1461  /* time offset between two EPI trains (up to 16 echoes = EPI trains) */
1463 
1464 
1465  /* maximum TE */
1466  if (existcv(optr)) {
1467  if (opautotr) {
1468  /* TR = minTR, i.e. the current TE is also the maximum TE */
1469  if (opautote)
1470  avmaxte = avminte;
1471  else if (existcv(opte))
1472  avmaxte = opte;
1473  else
1474  avmaxte = avminte;
1475  } else {
1476  /* maximum TE dependent on the chosen TR */
1477  avmaxte = optr - ksepi.seqctrl.ssi_time; /* maximum sequence duration for this TR (implies one slice per TR) */
1478  avmaxte -= ksepi.spoiler.duration; /* subtract ksepi.spoiler time */
1480  if (opnecho > 1) {
1481  avmaxte -= (opnecho - 1) * ksepi_interechotime; /* for multi-echo */
1482  }
1483  }
1484  } else {
1485  avmaxte = 1s;
1486  }
1487 
1488  if (opnecho == 2) {
1489  /* for opnecho == 2, the TE2 button appears although we have greyed it out (pite2nub = 0).
1490  Make avminte2/opte2 contain the actual number */
1491  avminte2 = avminte + ksepi_interechotime;
1492  avmaxte2 = avmaxte + ksepi_interechotime;
1493  opte2 = opte + ksepi_interechotime;
1494  }
1495 
1496  if (opautote) {
1497  setpopup(opte, PSD_OFF);
1498  cvoverride(opte, avminte, PSD_FIX_ON, PSD_EXIST_ON); /* AutoTE: force TE to minimum */
1499  } else if (existcv(opte)) {
1500  setpopup(opte, PSD_ON);
1501  if (opte < avminte)
1502  return ks_error("TE=%.1f too small. Please increase TE to %.1f", opte / 1000.0, avminte / 1000.0);
1503  if (opte > avmaxte)
1504  return ks_error("TE=%.1f too large. Please decrease to %.1f", opte / 1000.0, avmaxte / 1000.0);
1505  }
1506 
1507 
1508  return SUCCESS;
1509 
1510 } /* ksepi_TErange() */
KS_TRAP grad
Definition: KSFoundation.h:1491
int start2iso
Definition: KSFoundation.h:944
KS_TRAP grad
Definition: KSFoundation.h:1676
KS_SELRF selrfexc
Definition: ksepi_implementation.e:53
int ksepi_echotime_shifting
Definition: ksepi_implementation.e:136
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
KS_TRAP fcompphase
Definition: ksepi_implementation.e:60
KS_PHASER blipphaser
Definition: KSFoundation.h:1840
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
KS_EPI dynreftrain
Definition: ksepi_implementation.e:51
KS_PHASER zphaser
Definition: KSFoundation.h:1841
KS_EPI epitrain
Definition: ksepi_implementation.e:50
KS_TRAP pregrad
Definition: KSFoundation.h:1490
int duration
Definition: KSFoundation.h:1845
int ksepi_interechotime
Definition: ksepi_implementation.e:204
#define KS_RFSSP_POSTTIME
Definition: KSFoundation.h:153
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:49
KS_RF rf
Definition: KSFoundation.h:1485
KS_SELRF selrfref
Definition: ksepi_implementation.e:54
KS_TRAP fcompslice
Definition: ksepi_implementation.e:61
KS_TRAP postgrad
Definition: KSFoundation.h:1492
int iso2end
Definition: KSFoundation.h:945
int ssi_time
Definition: KSFoundation.h:1134
KS_TRAP spoiler
Definition: ksepi_implementation.e:52
int time2center
Definition: KSFoundation.h:1846
KS_TRAP readphaser
Definition: KSFoundation.h:1838
KS_TRAP diffgrad
Definition: ksepi_implementation.e:56
int ksepi_reflines
Definition: ksepi_implementation.e:162
int ksepi_echogap
Definition: ksepi_implementation.e:126
KS_TRAP diffgrad2
Definition: ksepi_implementation.e:57
KS_SELRF selrfref2
Definition: ksepi_implementation.e:55
int duration
Definition: KSFoundation.h:585
int ksepi_slicecheck
Definition: ksepi_implementation.e:109
int ramptime
Definition: KSFoundation.h:583
#define KS_RFSSP_PRETIME
Definition: KSFoundation.h:152

◆ ksepi_eval_inversion()

STATUS ksepi_eval_inversion ( KS_SEQ_COLLECTION seqcollection)

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

It is important that ksepi_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 ksepi_eval_tr(). ksinv_eval_multislice() sets seqcollection.evaltrdone = TRUE, which indicates that TR timing has been done. ksepi_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
1536  {
1537  STATUS status;
1538  int slperpass, npasses;
1539  int approved_TR = FALSE;
1540 
1541  status = KSINV_EVAL(seqcollection, 26, 27, 28, 29); /* args 2-6: integer X corresponds to opuserX CV */
1542  if (status != SUCCESS) return status;
1543 
1544  if (((int) *ksinv1_mode) == KSINV_OFF) {
1545  /* If no IR1 flag on, return */
1546  return SUCCESS;
1547  }
1548 
1549  /* interleaved slices in slice gap menu, force 2+ acqs */
1550  if (opileave)
1551  npasses = 2;
1552  else
1553  npasses = 1;
1554 
1555 
1556  while (approved_TR == FALSE) {
1557 
1558  /* Inversion (specific to 2D FSE/EPI type of PSDs). Must be done after all other sequence modules have been set up */
1559  slperpass = CEIL_DIV((int) exist(opslquant), npasses);
1560 
1561  if (KS_3D_SELECTED) {
1562  status = ks_calc_sliceplan(&ks_slice_plan, exist(opvquant), 1 /* seq 3DMS */);
1563  } else {
1564  status = ks_calc_sliceplan(&ks_slice_plan, exist(opslquant), slperpass);
1565  }
1566  if (status != SUCCESS) return status;
1567 
1568  /* ksinv_eval_multislice() sets seqcollection.evaltrdone = TRUE. This indicates that TR timing has been done.
1569  ksepi_eval_tr() check whether seqcollection.evaltrdone = TRUE to avoid that non-inversion TR timing overrides the
1570  intricate TR timing with inversion module(s). At the end of ksinv_eval_multislice(), TR validation and heat/SAR checks are done */
1572  if (status != SUCCESS) return status;
1573 
1574  if (existcv(optr) && opflair == OPFLAIR_INTERLEAVED && optr > ksinv_maxtr_t1flair) {
1575  /* T1-FLAIR */
1576  if (npasses > exist(opslquant)) {
1577  return ks_error("%s: T1-FLAIR: TR not met for single slice per TR", __FUNCTION__);
1578  }
1579  npasses++; /* increase #passes and call ksinv_eval_multislice() again with a new ks_slice_plan */
1580  } else {
1581  /* non-T1-FLAIR, or T1-FLAIR with approved TR value */
1582  approved_TR = TRUE;
1583  }
1584 
1585  } /* while (approved_TR == FALSE) */
1586 
1587 
1588  /* Check TR timing and SAR limits */
1590  if (status != SUCCESS) return status;
1591 
1592 
1593  return SUCCESS;
1594 
1595 } /* ksepi_eval_inversion() */
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
float * ksinv1_mode
Definition: KSInversion.e:140
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:49
int ksepi_scan_coreslice_nargs(const SCAN_INFO *slice_pos, int dabslice, int nargs, void **args)
Wrapper function to ksepi_scan_coreslice() with standardized input arguments
Definition: ksepi_implementation.e:2537
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
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

◆ ksepi_eval_tr()

STATUS ksepi_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 (ksepi_scan_sliceloop_nargs()) to the slice loop function (ksepi_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 ksepi_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
1622  {
1623  int timetoadd_perTR;
1624  STATUS status;
1625  int slperpass, min_npasses;
1626 
1627  if (seqcollection->evaltrdone == TRUE) {
1628  /*
1629  We cannot call GEReq_eval_TR() or GEReq_eval_checkTR_SAR(..., ksepi_scan_sliceloop_nargs, ...) if e.g. the inversion sequence module is used. This is because
1630  ksinv_scan_sliceloop() is used instead of ksepi_scan_sliceloop(). When ksinv1.params.mode != 0 (i.e. inversion sequence module on), the TR timing and
1631  heat/SAR limits checks are done in ksinv_eval_multislice(), which is called from ksepi_eval_inversion().
1632  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
1633  by setting evaltrdone = TRUE to avoid double processing here */
1634  return SUCCESS;
1635  }
1636 
1637  /* interleaved slices in slice gap menu, force 2+ acqs */
1638  if (opileave)
1639  min_npasses = 2;
1640  else
1641  min_npasses = 1;
1642 
1643  /* Calculate # slices per TR, # acquisitions and how much spare time we have within the current TR by running the slice loop. */
1644  status = GEReq_eval_TR(&slperpass, &timetoadd_perTR, min_npasses, seqcollection, ksepi_scan_sliceloop_nargs, 0, NULL);
1645  if (status != SUCCESS) return status;
1646 
1647  /* Calculate the slice plan (ordering) and passes (acqs). ks_slice_plan is passed to GEReq_predownload_store_sliceplan() in predownload() */
1648  if (KS_3D_SELECTED) {
1649  ks_calc_sliceplan(&ks_slice_plan, exist(opvquant), 1 /* seq 3DMS */);
1650  } else {
1651  ks_calc_sliceplan(&ks_slice_plan, exist(opslquant), slperpass);
1652  }
1653 
1654 
1655  /* We spread the available timetoadd_perTR evenly, by increasing the .duration of each slice by timetoadd_perTR/ksepi_slperpass */
1656  ksepi.seqctrl.duration = RUP_GRD(ksepi.seqctrl.duration + CEIL_DIV(timetoadd_perTR, ks_slice_plan.nslices_per_pass));
1657 
1658  /* Update SAR values in the UI (error will occur if the sum of sequence durations differs from optr) */
1660  if (status != SUCCESS) return status;
1661 
1662  /* Fill in the 'tmin' and 'tmin_total'. tmin_total is only like GEs use of the variable when TR = minTR */
1663  tmin = ksepi.seqctrl.min_duration;
1664  tmin_total = ksepi.seqctrl.duration;
1665 
1666  return SUCCESS;
1667 
1668 } /* ksepi_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
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
int duration
Definition: KSFoundation.h:1135
int nslices_per_pass
Definition: KSFoundation.h:1353
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:49
int min_duration
Definition: KSFoundation.h:1132
int ksepi_scan_sliceloop_nargs(int slperpass, int nargs, void **args)
Wrapper function to ksepi_scan_sliceloop() with standardized input arguments
Definition: ksepi_implementation.e:2709
int evaltrdone
Definition: KSFoundation.h:1303
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

◆ ksepi_eval_ssitime()

int ksepi_eval_ssitime ( )

The SSI time for the sequence

Return values
intSSI time in [us]
1679  {
1680 
1681  /* SSI time CV:
1682  Empirical finding on how much SSI time we need to update.
1683  But, use a longer SSI time when we write out data to file in scan() */
1684  ksepi_ssi_time = RUP_GRD(IMax(2,
1686  _ksepi_ssi_time.minval));
1687 
1688  /* Copy SSI CV to seqctrl field used by setssitime() */
1689  ksepi.seqctrl.ssi_time = RUP_GRD(ksepi_ssi_time);
1691 
1692  /* SSI time one-sequence-off workaround:
1693  We set the hardware ssitime in ks_scan_playsequence(), but it acts on the next sequence module, hence
1694  we aren't doing this correctly when using multiple sequence modules (as KSChemSat etc).
1695  One option would be to add a short dummy sequence ks_scan_playsequence(), but need to investigate
1696  if there is a better way. For now, let's assume the the necessary update time is the longest for
1697  the main sequence (this function), and let the ssi time for all other sequence modules (KSChemSat etc)
1698  have the same ssi time as the main sequence. */
1703 
1704  return ksepi_ssi_time;
1705 
1706 } /* ksepi_eval_ssitime() */
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:76
#define KSEPI_DEFAULT_SSI_TIME_ICEHARDWARE
Definition: ksepi_implementation.e:38
int ksspsat_ssi_time
Definition: KSSpSat.e:135
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:201
int kschemsat_ssi_time
Definition: KSChemSat.e:106
int ksinv_filltr_ssi_time
Definition: KSInversion.e:158
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:49
#define KSEPI_DEFAULT_SSI_TIME
Definition: ksepi_implementation.e:39
int ksepi_ssi_time
Definition: ksepi_implementation.e:173
int ks_syslimits_hasICEhardware()
Check for ICE Hardware (e.g. RX27+ on SIGNA Premier)
Definition: KSFoundation_common.c:186
int ssi_time
Definition: KSFoundation.h:1134
int ksinv_ssi_time
Definition: KSInversion.e:157

◆ ksepi_eval_scantime()

STATUS ksepi_eval_scantime ( )

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

the length of the scan

After setting the number of dummy scans based on the current TR, the ksepi_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
1722  {
1723 
1724  if (optr > 6s)
1725  ksepi_dda = 0;
1726  else if (optr >= 1s)
1727  ksepi_dda = 1;
1728  else if (optr > 350ms)
1729  ksepi_dda = 2;
1730  else
1731  ksepi_dda = 4;
1732 
1733  if (ksepi_dda > 0)
1734  ksepi_dda -= ksepi_ghostcorr; /* remove one dummy TR as the ghost corr TR is also acting as one */
1735 
1736  pitscan = ksepi_scan_scanloop();
1737 
1738  return SUCCESS;
1739 
1740 } /* ksepi_eval_scantime() */
float ksepi_scan_scanloop()
Plays out all volumes and passes of a single or multi-pass scan
Definition: ksepi_implementation.e:2850
int ksepi_dda
Definition: ksepi_implementation.e:174
int ksepi_ghostcorr
Definition: ksepi_implementation.e:178

◆ ksepi_check()

STATUS ksepi_check ( )

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

Return values
STATUSSUCCESS or FAILURE
1759  {
1760 
1761  /* Force the user to select the Echo Planar Imaging button. This error needs to be in cvcheck(), not in
1762  cvinit()/cveval() to avoid it to trigger also when Echo Planar Imaging has been selected.
1763  Without opepi = 1, the images won't show up correctly in the GE DB after the 1st volume */
1764 
1765  if (!KS_3D_SELECTED && opepi == PSD_OFF) {
1766  return ks_error("%s: Please first select the 'Echo Planar Imaging' button", ks_psdname);
1767  }
1768 
1769  if (existcv(opte) && existcv(opnex) && opautote == PSD_MINTE && opnex < 1.0) {
1770  ks_error("%s: TE = MinTE and NEX < 1 is not allowed", __FUNCTION__);
1771  }
1772 
1773  if (ksepi_reflines > ksepi.epitrain.etl) {
1774  ks_error("%s: ksepi_reflines cannot be larger than echo train length ", __FUNCTION__);
1775  }
1776 
1777  if (existcv(opnshots) && (opasset == ASSET_SCAN) && (opnshots > 1)) {
1778  return ks_error("%s: ASSET not compatible with multishot", __FUNCTION__);
1779  }
1780 
1781  if (existcv(opnshots) && existcv(opslquant) && existcv(optr) && (!opdiffuse) && (ksepi_multishot_control == KSEPI_MULTISHOT_B0VOLS)) {
1782  return ks_error("%s: Multishot control can only be 3 for DW-EPI", __FUNCTION__);
1783  }
1784 
1785  if (opasset != 0 && opasset != ASSET_SCAN) {
1786  return ks_error("%s: ASSET flag must be either 0 (OFF) or 2 (ON)", __FUNCTION__);
1787  }
1788 
1789  if (opdiffuse && oppseq == 2) {
1790  return ks_error("%s: Select SpinEcho for Diffusion", __FUNCTION__);
1791  }
1792 
1793 
1794  /* Pixel size in UI */
1795  piinplaneres = 1;
1796  ihinplanexres = opfov / ksepi.epitrain.read.res;
1797  ihinplaneyres = (opfov * opphasefov) / ksepi.epitrain.blipphaser.res;
1798 
1799  /* show echo spacing in UI */
1800  piesp = 1;
1801  ihesp = ksepi.epitrain.read.grad.duration / 1000.0;
1802 
1803  return SUCCESS;
1804 
1805 } /* ksepi_check() */
int res
Definition: KSFoundation.h:1678
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
KS_PHASER blipphaser
Definition: KSFoundation.h:1840
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
KS_TRAP grad
Definition: KSFoundation.h:1586
KS_EPI epitrain
Definition: ksepi_implementation.e:50
char ks_psdname[256]
Definition: GERequired.e:221
int etl
Definition: KSFoundation.h:1843
int res
Definition: KSFoundation.h:1577
KS_READTRAP read
Definition: KSFoundation.h:1837
float opfov
Definition: ksepi_implementation.e:92
int ksepi_reflines
Definition: ksepi_implementation.e:162
int duration
Definition: KSFoundation.h:585
int ksepi_multishot_control
Definition: ksepi_implementation.e:180

◆ ksepi_predownload_plot()

STATUS ksepi_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
Returns
STATUS SUCCESS or FAILURE
1838  {
1839  char tmpstr[1000];
1840 
1841  /* System wide (psd independent) option to disable plotting, to e.g. speed up UX on a slow MR show system */
1842  if (existfile("/usr/g/research/bin/ksdonotplot")) {
1843  return SUCCESS;
1844  }
1845 
1846 
1847 #ifdef PSD_HW
1848  sprintf(tmpstr, "/usr/g/mrraw/%s_objects.txt", ks_psdname);
1849 #else
1850  sprintf(tmpstr, "./%s_objects.txt", ks_psdname);
1851 #endif
1852  FILE *fp = fopen(tmpstr, "w");
1853 
1854  /* Note: 'fp' can be replaced with 'stdout' or 'stderr' to get these
1855  values printed out in the WTools window in simulation. However,
1856  heavy printing may result in that the WTools window closes,
1857  why we here write to a file ksepi_objects.txt instead */
1860  ks_print_selrf(ksepi.selrfref2, fp); /* opdualspinecho = 1, opdiffuse = 1 */
1861  ks_print_trap(ksepi.diffgrad, fp); /* opdiffuse = 1 */
1862  ks_print_trap(ksepi.diffgrad2, fp); /* opdualspinecho = 1, opdiffuse = 1 */
1866  fclose(fp);
1867 
1868 
1869  /* ks_plot_host():
1870  Plot each sequence module as a separate file (PNG/SVG/PDF depending on ks_plot_filefmt (GERequired.e))
1871  See KS_PLOT_FILEFORMATS in KSFoundation.h for options.
1872  Note that the phase encoding amplitudes corresponds to the first shot, as set by the call to ksepi_scan_seqstate below */
1874 
1876  int num_plans = sizeof(plans) / sizeof(KS_PHASEENCODING_PLAN *);
1877  ks_plot_host_seqctrl_manyplans(&ksepi.seqctrl, plans, num_plans);
1879 
1880  /* Sequence timing plot */
1884 
1885  /* ks_plot_tgt_reset():
1886  Creates sub directories and clear old files for later use of ksepi_scan_acqloop()->ks_plot_tgt_addframe().
1887  ks_plot_tgt_addframe() will only write in MgdSim (WTools) to avoid timing issues on the MR scanner. Hence,
1888  unlike ks_plot_host() and the sequence timing plot, one has to open MgdSim and press RunEntry (and also
1889  press PlotPulse several times after pressing RunEntry).
1890  ks_plot_tgt_reset() will create a 'makegif_***.sh' file that should be run in a terminal afterwards
1891  to create the animiated GIF from the dat files */
1893 
1894 
1895  return SUCCESS;
1896 
1897 } /* ksepi_predownload_plot() */
KS_PHASEENCODING_PLAN ref_peplan
Definition: ksepi_implementation.e:63
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:76
Phase encoding plan for the sequence (2D and 3D)
Definition: KSFoundation.h:1738
KS_SELRF selrfexc
Definition: ksepi_implementation.e:53
KS_PHASEENCODING_PLAN peplan
Definition: ksepi_implementation.e:64
STATUS ksepi_scan_seqstate(SCAN_INFO slice_info, int shot)
Sets the current state of all ksepi sequence objects being part of KSEPI_SEQUENCE
Definition: ksepi_implementation.e:2337
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
KS_EPI dynreftrain
Definition: ksepi_implementation.e:51
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:201
float ksepi_scan_scanloop()
Plays out all volumes and passes of a single or multi-pass scan
Definition: ksepi_implementation.e:2850
void ks_print_epi(KS_EPI epi, FILE *fp)
Writes out the contents of a KS_EPI sequence object for debugging
Definition: KSFoundation_host.c:5231
KS_EPI epitrain
Definition: ksepi_implementation.e:50
char ks_psdname[256]
Definition: GERequired.e:221
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:49
void ks_plot_host_seqctrl(KS_SEQ_CONTROL *ctrl, KS_PHASEENCODING_PLAN *plan)
Definition: KSFoundation_host.c:5594
void ks_plot_slicetime_begin()
Definition: KSFoundation_common.c:3396
KS_SELRF selrfref
Definition: ksepi_implementation.e:54
void ks_plot_host_seqctrl_manyplans(KS_SEQ_CONTROL *ctrl, KS_PHASEENCODING_PLAN **plan, const int num_plans)
Definition: KSFoundation_host.c:5599
void ks_plot_slicetime_end()
Definition: KSFoundation_common.c:3437
KS_PHASEENCODING_PLAN peplan
Definition: ksepi_implementation.e:82
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_PHASEENCODING_PLAN full_peplan
Definition: ksepi_implementation.e:62
KS_TRAP spoiler
Definition: ksepi_implementation.e:52
void ks_plot_tgt_reset(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_common.c:3445
KS_TRAP diffgrad
Definition: ksepi_implementation.e:56
KS_TRAP diffgrad2
Definition: ksepi_implementation.e:57
KS_SELRF selrfref2
Definition: ksepi_implementation.e:55
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

◆ ksepi_predownload_setrecon()

STATUS ksepi_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 ksepi.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
1911  {
1912 
1913  /* GERequired.e uses: rhuser32-25 (VRGF) and rhuser48 (scantime) */
1914 
1915 
1916  rhuser29 = (float) ksepi_fleet_num_ky; /* store for custom recon to know */
1917 
1918  rhuser30 = (float) ksepi_reflines; /* store for custom recon to know */
1919 
1920  rhuser31 = (float) ksepi_multishot_control; /* store for custom recon to know */
1921 
1922  rhuser47 = (float) opfphases; /* number of imaging volumes (may be less than rhnphases due to cal vols. opfphases does not show up in raw header) */
1923 
1924 
1925  rhrecon = 961; /* VRE recon using Matlab recon (recon_epi.m). See matlab/deploy/rpmbuild on how to make an RPM */
1926 
1927  return SUCCESS;
1928 
1929 } /* ksepi_predownload_setrecon() */
int ksepi_reflines
Definition: ksepi_implementation.e:162
int ksepi_multishot_control
Definition: ksepi_implementation.e:180
int ksepi_fleet_num_ky
Definition: ksepi_implementation.e:156

◆ ksepi_pg_fleet()

STATUS ksepi_pg_fleet ( int  start_time)

The fleet pulse sequence for GRAPPA calibration

This is the fleet pulse sequence in ksepi.e using the sequence objects in KSEPI_FLEET_SEQUENCE with the sequence module name "ksepifleet" (= ksepi_fleet.seqctrl.description)

Return values
STATUSSUCCESS or FAILURE
2201  {
2202  KS_SEQLOC tmploc = KS_INIT_SEQLOC;
2203 
2204  if (ksepi_fleet == FALSE) {
2205  return SUCCESS;
2206  }
2207 
2208  if (start_time < KS_RFSSP_PRETIME) {
2209  return ks_error("%s: 1st arg (pos start) must be at least %d us", __FUNCTION__, KS_RFSSP_PRETIME);
2210  }
2211 
2212  /*******************************************************************************************************
2213  * RF Excitation
2214  *******************************************************************************************************/
2215  tmploc.ampscale = 1.0;
2216  tmploc.pos = RUP_GRD(start_time + KS_RFSSP_PRETIME);
2217  tmploc.board = ZGRAD;
2218 
2219  /* N.B.: ks_pg_selrf()->ks_pg_rf() detects that ksepi_fleetseq.selrfexc is an excitation pulse
2220  (ksepi_fleetseq.selrfexc.rf.role = KS_RF_ROLE_EXC) and will also set ksepi_fleetseq.seqctrl.momentstart
2221  to the absolute position in [us] of the isocenter of the RF excitation pulse */
2222  if (ks_pg_selrf(&ksepi_fleetseq.selrfexc, tmploc, &ksepi_fleetseq.seqctrl) == FAILURE)
2223  return FAILURE;
2224 
2227 
2228  /*******************************************************************************************************
2229  * EPI echo time shifting
2230  *******************************************************************************************************/
2231  if (ksepi_echotime_shifting == TRUE) {
2232  tmploc.board = KS_ALL;
2233  if (ks_pg_wait(&ksepi_fleetseq.pre_delay, tmploc, &ksepi_fleetseq.seqctrl) != SUCCESS) {
2234  return FAILURE;
2235  }
2236  tmploc.pos += GRAD_UPDATE_TIME;
2237  }
2238 
2239  /*******************************************************************************************************
2240  * EPI readout including de/rephasers on freq and phase encoding axes (net zero moment on both axes)
2241  *******************************************************************************************************/
2242 
2243  if (ksepi_slicecheck)
2244  tmploc.board = KS_FREQZ_PHASEY;
2245  else
2246  tmploc.board = KS_FREQX_PHASEY;
2247  tmploc.ampscale = ksepi_readsign;
2248  if (ks_pg_epi(&ksepi_fleetseq.epitrain, tmploc, &ksepi_fleetseq.seqctrl) == FAILURE) {
2249  return FAILURE;
2250  }
2251  tmploc.pos += ksepi_fleetseq.epitrain.duration; /* end of EPI (incl. x/y rephasers, but not zphaser) */
2252 
2253  /*******************************************************************************************************
2254  * Gradient spoilers on Y and Z (at the same time)
2255  *******************************************************************************************************/
2256  tmploc.ampscale = 1.0;
2257 
2258  tmploc.board = YGRAD;
2259  if (ks_pg_trap(&ksepi_fleetseq.spoiler, tmploc, &ksepi_fleetseq.seqctrl) == FAILURE)
2260  return FAILURE;
2261  tmploc.board = ZGRAD;
2262  if (ks_pg_trap(&ksepi_fleetseq.spoiler, tmploc, &ksepi_fleetseq.seqctrl) == FAILURE)
2263  return FAILURE;
2264 
2265  tmploc.pos += ksepi_fleetseq.spoiler.duration;
2266 
2267  /*******************************************************************************************************
2268  * EPI echo time shifting
2269  *******************************************************************************************************/
2270  if (ksepi_echotime_shifting == TRUE) {
2271  tmploc.pos += GRAD_UPDATE_TIME;
2272  tmploc.board = KS_ALL;
2273  if (ks_pg_wait(&ksepi_fleetseq.post_delay, tmploc, &ksepi.seqctrl) != SUCCESS) {
2274  return FAILURE;
2275  }
2276  tmploc.pos += IMax(2, psd_grd_wait, psd_rf_wait) + GRAD_UPDATE_TIME;
2278  }
2279 
2280  /*******************************************************************************************************
2281  * Set the minimal sequence duration (ksepi.seqctrl.min_duration) by calling
2282  * ks_eval_seqctrl_setminduration()
2283  *******************************************************************************************************/
2284 
2285  /* make sure we are divisible by GRAD_UPDATE_TIME (4us) */
2286  tmploc.pos = RUP_GRD(tmploc.pos);
2287 
2288 #ifdef HOST_TGT
2289  /* On HOST only: Sequence duration (ksepi_fleetseq.seqctrl.ssi_time must be > 0 and is added to ksepi_fleetseq.seqctrl.min_duration in ks_eval_seqctrl_setminduration() */
2291  ks_eval_seqctrl_setminduration(&ksepi_fleetseq.seqctrl, tmploc.pos); /* tmploc.pos now corresponds to the end of last gradient in the sequence */
2292 #endif
2293 
2294  /*******************************************************************************************************
2295  * Phase encoding table
2296  * Need to call this in ksepi_pg_fleet() so it is run both on HOST and TGT. This, since the phase table
2297  * is dynamically allocated in ks_phaseencoding_generate_epi()->ks_phaseencoding_resize()
2298  *******************************************************************************************************/
2299 
2300  if (ks_phaseencoding_generate_epi(&ksepi_fleetseq.peplan, "Fully sampled EPI volume",
2307  ksepi_caipi) == FAILURE) {
2308  return FAILURE;
2309  }
2310 
2311  /* set EPI dephasers and blips to the first shot so we get the correct plots in WTools */
2313 
2314  return SUCCESS;
2315 
2316 } /* ksepi_pg_fleet() */
int ksepi_readsign
Definition: ksepi_implementation.e:127
Definition: KSFoundation.h:1919
KS_TRAP grad
Definition: KSFoundation.h:1491
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:76
int R
Definition: KSFoundation.h:1680
int pos
Definition: KSFoundation.h:389
int ksepi_echotime_shifting
Definition: ksepi_implementation.e:136
KS_WAIT pre_delay
Definition: ksepi_implementation.e:80
int ksepi_eval_ssitime()
The SSI time for the sequence
Definition: ksepi_implementation.e:1679
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
ks_enum_sweep_order
Definition: KSFoundation.h:1902
KS_PHASER blipphaser
Definition: KSFoundation.h:1840
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
int numlinestoacq
Definition: KSFoundation.h:1684
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
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:201
STATUS ks_pg_wait(KS_WAIT *wait, KS_SEQLOC loc, KS_SEQ_CONTROL *ctrl) WARN_UNUSED_RESULT
Places a KS_WAIT sequence object on all boards at some position in the pulse sequence
Definition: KSFoundation_common.c:2287
int board
Definition: KSFoundation.h:388
KS_PHASER zphaser
Definition: KSFoundation.h:1841
Definition: KSFoundation.h:1924
float ampscale
Definition: KSFoundation.h:390
Definition: KSFoundation.h:1926
int duration
Definition: KSFoundation.h:1845
#define KS_RFSSP_POSTTIME
Definition: KSFoundation.h:153
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:49
KS_RF rf
Definition: KSFoundation.h:1485
KS_TRAP spoiler
Definition: ksepi_implementation.e:78
STATUS ks_pg_epi(KS_EPI *epi, KS_SEQLOC loc, KS_SEQ_CONTROL *ctrl) WARN_UNUSED_RESULT
Places out a KS_EPI object (EPI train including dephaser and rephaser gradients)
Definition: KSFoundation_common.c:2704
Definition: KSFoundation.h:1902
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
KS_PHASEENCODING_PLAN peplan
Definition: ksepi_implementation.e:82
typedef struct used as argument to ks_pg_*** functions to control where and when to place a sequence ...
Definition: KSFoundation.h:387
KS_WAIT post_delay
Definition: ksepi_implementation.e:81
KS_TRAP postgrad
Definition: KSFoundation.h:1492
int iso2end
Definition: KSFoundation.h:945
STATUS ks_phaseencoding_generate_epi(KS_PHASEENCODING_PLAN *phaseenc_plan_ptr, const char *const desc, const KS_EPI *epitrain, const ks_enum_epiblipsign blipsign, const ks_enum_pf_earlylate_te pf_direction, const int numileavestoacq, ks_enum_sweep_order sweep_order, int numsegments, const int caipi_delta)
EPI: Makes a KS_PHASEENCODING_PLAN suitable for 2D or 3D epi
Definition: KSFoundation_common.c:833
int ssi_time
Definition: KSFoundation.h:1134
int ksepi_blipsign
Definition: ksepi_implementation.e:135
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_enum_epiblipsign
Definition: KSFoundation.h:1929
int ksepi_echotime_shifting_sumdelay
Definition: ksepi_implementation.e:210
int psd_grd_wait
void ks_scan_epi_shotcontrol(KS_EPI *epi, int echo, SCAN_INFO sliceinfo, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot, int exc, float rcvphase)
Changes the gradient state of a KS_EPI object for the given slice information
Definition: KSFoundation_tgt.c:1089
#define KS_INIT_SEQLOC
Definition: KSFoundation.h:208
int duration
Definition: KSFoundation.h:585
int ksepi_slicecheck
Definition: ksepi_implementation.e:109
int psd_rf_wait
int ksepi_fleet
Definition: ksepi_implementation.e:153
KS_SELRF selrfexc
Definition: ksepi_implementation.e:79
int ramptime
Definition: KSFoundation.h:583
endif SCAN_INFO ks_scan_info[SLTAB_MAX]
Definition: GERequired.e:215
Definition: KSFoundation.h:1899
KS_EPI epitrain
Definition: ksepi_implementation.e:77
#define KS_RFSSP_PRETIME
Definition: KSFoundation.h:152
int ksepi_caipi
Definition: ksepi_implementation.e:142

◆ ksepi_fleet_scan_seqstate()

STATUS ksepi_fleet_scan_seqstate ( const SCAN_INFO *  slice_info,
int  shot 
)
2375  {
2376  float exc_rfphase;
2377  int exc = 0; /* NEX index. Future use */
2378 
2379  /* RF frequency & phase */
2380  if (ksepi_rfspoiling) {
2383  } else {
2384  exc_rfphase = 0;
2385  }
2386 
2387  if (slice_info != NULL) {
2388  ks_scan_rotate(*slice_info);
2390  ks_scan_selrf_setfreqphase(&ksepi_fleetseq.selrfexc, 0, *slice_info, exc_rfphase);
2391  ks_scan_epi_shotcontrol(&ksepi_fleetseq.epitrain, 0, *slice_info, &ksepi_fleetseq.peplan, shot, exc, exc_rfphase);
2392  } else {
2394  }
2395 
2396  return SUCCESS;
2397 } /* ksepi_fleet_scan_seqstate() */
void ks_scan_rf_on(KS_RF *rf, int instanceno)
Resets the amplitude of one or all instances of an RF pulse (KS_RF)
Definition: KSFoundation_tgt.c:442
float ks_scan_rf_phase_spoiling(int counter)
Returns spoiling phase for a given RF counter
Definition: KSFoundation_common.c:3883
int ksepi_rfspoiling
Definition: ksepi_implementation.e:111
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:201
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
void ks_scan_selrf_setfreqphase(KS_SELRF *selrf, int instanceno, SCAN_INFO sliceinfo, float rfphase)
Updates the frequency and phase of one or all instances of a slice selective RF pulse (KS_SELRF)...
Definition: KSFoundation_tgt.c:581
KS_RF rf
Definition: KSFoundation.h:1485
KS_PHASEENCODING_PLAN peplan
Definition: ksepi_implementation.e:82
void ks_scan_rotate(SCAN_INFO slice_info)
Performs a rotation of the logical system on hardware (WARP)
Definition: KSFoundation_tgt.c:989
void ks_scan_epi_shotcontrol(KS_EPI *epi, int echo, SCAN_INFO sliceinfo, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot, int exc, float rcvphase)
Changes the gradient state of a KS_EPI object for the given slice information
Definition: KSFoundation_tgt.c:1089
KS_SELRF selrfexc
Definition: ksepi_implementation.e:79
int rfspoiling_phase_counter
Definition: ksepi_implementation.e:2897
KS_EPI epitrain
Definition: ksepi_implementation.e:77

◆ ksepi_scan_rf_off()

void ksepi_scan_rf_off ( )

Sets all RF pulse amplitudes to zero

Returns
void
2406  {
2407  ks_scan_rf_off(&ksepi.selrfexc.rf, INSTRALL);
2408  ks_scan_rf_off(&ksepi.selrfref.rf, INSTRALL);
2409 
2410  if (opdiffuse && opdualspinecho) {
2411  ks_scan_rf_off(&ksepi.selrfref2.rf, INSTRALL);
2412  }
2413 }
KS_SELRF selrfexc
Definition: ksepi_implementation.e:53
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
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
KS_RF rf
Definition: KSFoundation.h:1485
KS_SELRF selrfref
Definition: ksepi_implementation.e:54
KS_SELRF selrfref2
Definition: ksepi_implementation.e:55

◆ ksepi_fleet_scan_coreslice()

int ksepi_fleet_scan_coreslice ( const SCAN_INFO *  slice_pos,
int  dabslice,
int  shot 
)
2557  {
2558  int time = 0;
2559  float tloc = 0.0;
2560 
2561  if (ksepi_fleetseq.seqctrl.duration == 0) {
2562  return 0;
2563  }
2564 
2565  if (slice_pos != NULL)
2566  tloc = slice_pos->optloc; /* real slice */
2567  else
2568  dabslice = KS_NOTSET; /* shut off data acq if false slice */
2569 
2570  ksepi_fleet_scan_seqstate(slice_pos, (rspent == L_SCAN) ? shot : KS_NOTSET);
2571  KS_PHASEENCODING_COORD coord = ks_phaseencoding_get(&ksepi_fleetseq.peplan, 0, shot); /* coord to first line of EPI train */
2572  if (KS_3D_SELECTED) {
2573  if (ks_scan_info[1].optloc > ks_scan_info[0].optloc)
2574  dabslice = (opslquant * opvquant - 1) - coord.kz;
2575  else
2576  dabslice = coord.kz;
2577  }
2581  slice_pos == NULL ? KS_PLOT_NO_EXCITATION : KS_PLOT_STANDARD);
2582 
2583  return time; /* in [us] */
2584 
2585 } /* ksepi_fleet_scan_coreslice() */
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:76
#define KS_NOTSET
Definition: KSFoundation.h:103
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:201
int duration
Definition: KSFoundation.h:1135
void ks_scan_epi_loadecho(KS_EPI *epi, int echo, int storeecho, int slice, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot)
Definition: KSFoundation_tgt.c:1270
int kz
Definition: KSFoundation.h:1706
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
int ks_scan_playsequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1368
Definition: KSFoundation.h:336
KS_PHASEENCODING_PLAN peplan
Definition: ksepi_implementation.e:82
Definition: KSFoundation.h:335
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
STATUS ksepi_fleet_scan_seqstate(const SCAN_INFO *slice_info, int shot)
Definition: ksepi_implementation.e:2375
int rspent
Definition: GERequired.e:2626
KS_SELRF selrfexc
Definition: ksepi_implementation.e:79
endif SCAN_INFO ks_scan_info[SLTAB_MAX]
Definition: GERequired.e:215
float slthick
Definition: KSFoundation.h:1487
KS_EPI epitrain
Definition: ksepi_implementation.e:77

◆ ksepi_fleet_scan_sliceloop()

int ksepi_fleet_scan_sliceloop ( int  slperpass,
int  volindx,
int  passindx 
)
2634  {
2635  int time = 0;
2636  int slloc, sltimeinpass, shot;
2637  SCAN_INFO centerposition = ks_scan_info[0]; /* first slice chosen here, need only rotation stuff */
2638 
2639  (void) volindx;
2640 
2641  if (KS_3D_SELECTED) {
2642  int centerslice = opslquant/2;
2643  /* for future 3D multislab support, let passindx update centerposition */
2644  centerposition.optloc = (ks_scan_info[centerslice-1].optloc + ks_scan_info[centerslice].optloc)/2.0;
2645  }
2646 
2647  for (sltimeinpass = 0; sltimeinpass < slperpass; sltimeinpass++) {
2648 
2649  SCAN_INFO *current_slice = &centerposition;
2650  if (!KS_3D_SELECTED) {
2651  /* slice location from slice plan */
2652  slloc = ks_scan_getsliceloc(&ks_slice_plan, passindx, sltimeinpass);
2653  current_slice = (slloc != KS_NOTSET) ? &ks_scan_info[slloc] : NULL;
2654  }
2655 
2656  for (shot = -ksepi_fleet_dda; shot < ksepi_fleetseq.peplan.num_shots; shot++) {
2657 
2658  if (ksepi_echotime_shifting == TRUE) {
2659  KS_PHASEENCODING_COORD coord = ks_phaseencoding_get(&ksepi_fleetseq.peplan, 0, shot); /* coord to first line of EPI train */
2660  const int kyshot = coord.ky % ksepi_fleetseq.peplan.phaser->R;
2661 
2663  int post_delay = 0;
2664 
2665  if (blipsign == KS_EPI_POSBLIPS) {
2666  post_delay = (kyshot <= 0) ? GRAD_UPDATE_TIME : RUP_GRD((int) (ksepi_echotime_shifting_shotdelay * kyshot));
2667  } else if (blipsign == KS_EPI_NEGBLIPS) {
2668  post_delay = (kyshot <= 0) ? GRAD_UPDATE_TIME : RUP_GRD((int) (ksepi_echotime_shifting_shotdelay * (ksepi_fleetseq.peplan.phaser->R-1-kyshot)));
2669  }
2670 
2672  ks_scan_wait(&ksepi.post_delay, post_delay);
2673  }
2674 
2675  time += ksepi_fleet_scan_coreslice(current_slice, (shot >= 0) ? sltimeinpass : KS_NOTSET, (shot >= 0) ? shot : KS_NOTSET);
2676 
2677  }
2678  ks_plot_slicetime_endofslicegroup(ksepi_fleet_dda > 0 ? "FLEET shots (incl dummies)" : "FLEET shots");
2679  }
2680 
2682 
2683  return time;
2684 
2685 }
int volindx
Definition: ksfse_implementation.e:2849
int R
Definition: KSFoundation.h:1680
int num_shots
Definition: KSFoundation.h:1739
#define KS_NOTSET
Definition: KSFoundation.h:103
void ks_plot_slicetime_endofpass(KS_PLOT_PASS_MODE)
Definition: KSFoundation_common.c:3412
int ksepi_echotime_shifting
Definition: ksepi_implementation.e:136
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
float ksepi_echotime_shifting_shotdelay
Definition: ksepi_implementation.e:207
#define KS_3D_SELECTED
Definition: KSFoundation.h:177
int ksepi_fleet_dda
Definition: ksepi_implementation.e:155
int ky
Definition: KSFoundation.h:1705
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:201
const KS_PHASER * phaser
Definition: KSFoundation.h:1743
void ks_plot_slicetime_endofslicegroup(const char *desc)
Definition: KSFoundation_common.c:3428
ks_enum_epiblipsign ks_scan_epi_verify_phaseenc_plan(KS_EPI *epi, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot)
Definition: KSFoundation_tgt.c:1050
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
Definition: KSFoundation.h:1929
int passindx
Definition: ksfse_implementation.e:2849
KS_PHASEENCODING_PLAN peplan
Definition: ksepi_implementation.e:82
void ks_scan_wait(KS_WAIT *wait, int waitperiod)
Updates the wait period of all instances of a KS_WAIT sequence object. The value of waitperiod must n...
Definition: KSFoundation_tgt.c:151
ks_enum_epiblipsign
Definition: KSFoundation.h:1929
int ksepi_echotime_shifting_sumdelay
Definition: ksepi_implementation.e:210
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 ksepi_fleet_scan_coreslice(const SCAN_INFO *slice_pos, int dabslice, int shot)
Definition: ksepi_implementation.e:2557
KS_WAIT pre_delay
Definition: ksepi_implementation.e:58
Definition: KSFoundation.h:1929
Definition: KSFoundation.h:340
endif SCAN_INFO ks_scan_info[SLTAB_MAX]
Definition: GERequired.e:215
KS_WAIT post_delay
Definition: ksepi_implementation.e:59
KS_EPI epitrain
Definition: ksepi_implementation.e:77

◆ ksepi_scan_init()

STATUS ksepi_scan_init ( void  )

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

Return values
STATUSSUCCESS or FAILURE
2912  {
2913 
2914  GEReq_initRSP();
2915 
2916  /* Here goes code common for APS2, MPS2 and SCAN */
2917 
2918  ks_scan_switch_to_sequence(&ksepi.seqctrl); /* switch to main sequence */
2919  scopeon(&seqcore); /* Activate scope for core */
2920  syncon(&seqcore); /* Activate sync for core */
2921  setssitime(ksepi.seqctrl.ssi_time / HW_GRAD_UPDATE_TIME);
2922 
2923  /* can we make these independent on global rsptrigger and rsprot in orderslice? */
2924  settriggerarray( (short) ks_slice_plan.nslices_per_pass, rsptrigger);
2925 
2927 
2928  return SUCCESS;
2929 
2930 } /* ksepi_scan_init() */
void ks_scan_switch_to_sequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1356
STATUS setssitime(long)
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
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
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:49
int ssi_time
Definition: KSFoundation.h:1134
KS_SLICE_PLAN ks_slice_plan
Definition: GERequired.e:217
int rfspoiling_phase_counter
Definition: ksepi_implementation.e:2897

◆ ksepi_scan_prescanloop()

STATUS ksepi_scan_prescanloop ( int  nloops,
int  dda 
)

Prescan loop called from both APS2 and MPS2 entry points

Return values
STATUSSUCCESS or FAILURE
2940  {
2941  int i, echoindx, sliceindx, shotindx, sltimeinpass;
2942  int slloc;
2943 
2944  /* turn off receivers for all echoes (thanks to slice = KS_NOTSET) */
2945  for (echoindx = 0; echoindx < opnecho; echoindx++) {
2946  ks_scan_epi_loadecho(&ksepi.epitrain, echoindx, echoindx, KS_NOTSET, NULL, KS_NOTSET);
2947  }
2948  if (ksepi_reflines > 0) {
2949  /* store phase reference echo as opnecho */
2951  }
2952 
2953  /* Diffusion gradients must be off during prescan to get the correct receiver gain */
2954  if (opdiffuse) {
2955  ksepi_diffusion_scan_diffamp(&ksepi, KS_NOTSET); /* KS_NOTSET zeroes all diffusion gradient amplitudes */
2956  }
2957 
2958  /* play dummy scans to get into steady state */
2959  for (i = -dda; i < nloops; i++) {
2960 
2961  /* loop over slices */
2962  for (sltimeinpass = 0; sltimeinpass < ks_slice_plan.nslices_per_pass; sltimeinpass++) {
2963 
2964  /* slice location from slice plan */
2965  slloc = ks_scan_getsliceloc(&ks_slice_plan, 0, sltimeinpass);
2966 
2967  /* modify sequence for next playout */
2969 
2970  /* data routing control */
2971  echoindx = 0; /* just to 1st echo for prescan */
2972  sliceindx = 0;
2973  shotindx = 0;
2974  if (i >= 0) {
2975  ks_scan_epi_loadecho(&ksepi.epitrain, echoindx, echoindx, sliceindx, NULL, shotindx);
2976  }
2977 
2979 
2980  } /* for slices */
2981 
2982  } /* for nloops */
2983 
2984  return SUCCESS;
2985 
2986 } /* ksepi_scan_prescanloop() */
void ksepi_diffusion_scan_diffamp(KSEPI_SEQUENCE *ksepi, int volindx)
Definition: ksepi_implementation_diffusion.e:882
#define KS_NOTSET
Definition: KSFoundation.h:103
STATUS ksepi_scan_seqstate(SCAN_INFO slice_info, int shot)
Sets the current state of all ksepi sequence objects being part of KSEPI_SEQUENCE
Definition: ksepi_implementation.e:2337
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
int32_t i
Definition: KSFoundation_tgt.c:1389
KS_EPI dynreftrain
Definition: ksepi_implementation.e:51
void ks_scan_epi_loadecho(KS_EPI *epi, int echo, int storeecho, int slice, KS_PHASEENCODING_PLAN *phaseenc_plan, int shot)
Definition: KSFoundation_tgt.c:1270
KS_EPI epitrain
Definition: ksepi_implementation.e:50
int nslices_per_pass
Definition: KSFoundation.h:1353
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:49
int ks_scan_playsequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1368
KS_SLICE_PLAN ks_slice_plan
Definition: GERequired.e:217
int ksepi_reflines
Definition: ksepi_implementation.e:162
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
endif SCAN_INFO ks_scan_info[SLTAB_MAX]
Definition: GERequired.e:215

◆ ksepi_diffusion_readtensorfile()

STATUS ksepi_diffusion_readtensorfile ( DIFFSCHEME  diffscheme,
int  nb0,
int  ndirs 
)
88  {
89  int i;
90  FILE *fp;
91  char tmpstr[1000];
92  int lineskip = TRUE;
93  char matchstr[10];
94  int matchlen;
95 
96 #ifdef PSD_HW
97  const char *tensorfile = "/usr/g/bin/tensor.dat";
98 #else
99  const char *tensorfile = "./tensor.dat";
100 #endif
101 
102  if (nb0 < 0) {
103  return ks_error("# T2 (b0) images must be > 0");
104  }
105 
106  if (ndirs < 6 || ndirs > 150) {
107  return ks_error("# diff. directions must be in range [6,150]");
108  }
109 
110  /* clear table */
111  for (i = 0; i < MAX_DIFSCHEME_LENGTH; i++) {
112  diffscheme[XGRAD][i] = diffscheme[YGRAD][i] = diffscheme[ZGRAD][i] = 0.0;
113  }
114 
115 
116  /* read from tensor.dat */
117 
118  if ((fp = fopen(tensorfile, "r" )) == NULL) {
119  return ks_error("%s: Could not open file: %s", __FUNCTION__, tensorfile);
120  }
121 
122  /* what to line content look for in the file */
123  sprintf(matchstr, "%d", ndirs);
124  matchlen = strlen(matchstr);
125 
126  while (lineskip) {
127  fgets(tmpstr, 1000, fp);
128  lineskip = strncmp(matchstr, tmpstr, matchlen);
129  }
130 
131  for (i = 0; i < ndirs; i++) {
132  if (fgets(tmpstr, 1000, fp) == NULL) {
133  ks_error("%s: Error reading file: %s for #dirs = %d, direction %d", __FUNCTION__, tensorfile, ndirs, i);
134  }
135  sscanf(tmpstr, "%f %f %f", &diffscheme[XGRAD][nb0 + i], &diffscheme[YGRAD][nb0 + i], &diffscheme[ZGRAD][nb0 + i]);
136  }
137 
138  fclose(fp);
139 
140 
141  return SUCCESS;
142 }
DIFFSCHEME diffscheme
Definition: ksepi_implementation_diffusion.e:76
#define MAX_DIFSCHEME_LENGTH
Definition: ksepi_implementation_diffusion.e:36
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int32_t i
Definition: KSFoundation_tgt.c:1389

◆ ksepi_diffusion_getmaxb()

float ksepi_diffusion_getmaxb ( )
146  {
147  float maxb = 0.0;
148 #ifdef PSD_HW
149  int i;
150  /* On the MR scanner, opval should be set to the highest bvalue in the bvalstab list */
151  for (i = 0; i < opnumbvals; i++) {
152  if (bvalstab[i] > maxb) {
153  maxb = bvalstab[i];
154  }
155  }
156 #else
157  maxb = opbval;
158 #endif
159 
160  return maxb;
161 }
int32_t i
Definition: KSFoundation_tgt.c:1389

◆ ksepi_diffusion_set_heat_scaling()

void ksepi_diffusion_set_heat_scaling ( DIFFSCHEME  diffscheme)
163  {
164  int i,N;
165  float tmpx = 0, tmpy = 0, tmpz = 0;
166  N = opdifnumt2 + ndiffdirs;
167  for (i = 0; i < N; i++) {
168  tmpx += diffscheme[XGRAD][i] * diffscheme[XGRAD][i];
169  tmpy += diffscheme[YGRAD][i] * diffscheme[YGRAD][i];
170  tmpz += diffscheme[ZGRAD][i] * diffscheme[ZGRAD][i];
171  }
172  tmpx = sqrt(tmpx/N);
173  tmpy = sqrt(tmpy/N);
174  tmpz = sqrt(tmpz/N);
175 
179 }
DIFFSCHEME diffscheme
Definition: ksepi_implementation_diffusion.e:76
float ksepi_diffusion_scaleZ_heatcal
Definition: ksepi_implementation_diffusion.e:63
int32_t i
Definition: KSFoundation_tgt.c:1389
int ndiffdirs
Definition: ksepi_implementation_diffusion.e:77
float ksepi_diffusion_scaleX_heatcal
Definition: ksepi_implementation_diffusion.e:61
float ksepi_diffusion_scaleY_heatcal
Definition: ksepi_implementation_diffusion.e:62

◆ ksepi_diffusion_init_UI()

STATUS ksepi_diffusion_init_UI ( )
181  {
182  int i;
183 
184  if (opdiffuse != KS_EPI_DIFFUSION_ON) {
185  return SUCCESS;
186  }
187 
188  /* Number of b-values menu (opnumbvals) */
189  pinumbnub = 63;
190  pinumbval2 = 1;
191  pinumbval3 = 2;
192  pinumbval4 = 3;
193  pinumbval5 = 4;
194  pinumbval6 = 5;
195 
196  cvmax(opbval, 30000);
197  cvdef(opbval, 1000);
198  opbval = _opbval.defval;
199 
200  /* b-value table menu */
201  pibvalstab = 1; /* show bvalue table */
202  if (existcv(opnumbvals) == FALSE) {
203  /* until number of b-value has been selected, set up a range of b-values */
204  for (i = 0; i < 10; i++)
205  bvalstab[i] = 1000 + 500 * i;
206  }
207 
208  avminbvalstab = 10;
209  avmaxbvalstab = 20000;
210 
211  pidifnextab = 1; /* show NEX input in table, but only allow 1 */
212  avmindifnextab = 1;
213  avmaxdifnextab = 1;
214 
215  /* Hide number of NEX for T2 menu (opdifnext2) */
216  pidifnext2nub = 0;
217  avmindifnext2 = 1;
218  avmaxdifnext2 = 1;
219  cvoverride(opdifnext2, 1, PSD_FIX_ON, PSD_EXIST_ON);
220  cvoverride(rhdifnext2, 1, PSD_FIX_ON, PSD_EXIST_ON);
221 
222 
223  /* Number of T2 menu (opdifnumt2) */
224  pidifnumt2defval = 1;
225  cvdef(opdifnumt2, pidifnumt2defval);
226  opdifnumt2 = pidifnumt2defval;
227  pidifnumt2nub = 15;
228  pidifnumt2val2 = 1;
229  pidifnumt2val3 = 2;
230  pidifnumt2val4 = 3;
231 
232  /* Number of diffusion directions menu (opdifnumdirs) */
233  pidifnumdirsnub = 15;
234  pidifnumdirsdefval = 6;
235  pidifnumdirsval2 = 6;
236  pidifnumdirsval3 = 15;
237  pidifnumdirsval4 = 25;
238 
239  /* no synthetic bvalues menu */
240  pinumsynbnub = 0;
241 
242  /* Only allow MinTE (i.e. partial Fourier ky) or MinFullTE */
243  pitetype = PSD_LABEL_TE_EFF; /* alt. PSD_LABEL_TE_EFF */
244  cvdef(opte, 200ms);
245  opte = _opte.defval;
246  pite1nub = 6;
247  pite1val2 = PSD_MINIMUMTE;
248  pite1val3 = PSD_MINFULLTE;
249 
250  /* Upsample DWI data to nearest power of 2 */
252 
253  /* show shots 1-5 */
254  pishotval2 = 1;
255  pishotval3 = 2;
256  pishotval4 = 3;
257  pishotval5 = 4;
258  pishotval6 = 5;
259  cvdef(opnshots, 3);
260  opnshots = _opnshots.defval;
261 
262 
263  /* Don't allow multiple acqs for DW-EPI */
264  pitrnub = 2; /* Minimum */
265  pitrval2 = PSD_MINIMUMTR;
266  piisil = PSD_OFF;
267 
268  /* Optimize TE / super G check box */
269 #if EPIC_RELEASE >= 27
270  pimintediflabel = HAVE_PREMIER_GRADIENTS; /* Label indicator: 0 - Optimize TE, 1 - Super G */
271  pimintedifvis = HAVE_PREMIER_GRADIENTS; /* Visibility of the "Optimize TE"/"Super G" button : 0 - invisible, 1 - visible */
272 #endif
273 
274 
275  /* if ks_gheatfact gets too low, it will trip the gradients during scanning */
276  float lowlimit_gheat = (ksepi_diffusion_getmaxb() > 1000.0) ? 0.5 : 0.25;
277  if (ks_gheatfact < lowlimit_gheat) {
278  cvoverride(ks_gheatfact, lowlimit_gheat, PSD_FIX_OFF, PSD_EXIST_ON);
279  }
280 
281  /* Max diffusion amplitude to work with [G/cm] (based on trial and error) */
283  if (opmintedif) {
284 
285  if (ks_gheatfact < 0.8) {
286  cvoverride(ks_gheatfact, 0.8, PSD_FIX_OFF, PSD_EXIST_ON);
287  }
288 
289  /* 70 mT/m with longer TR */
290  _ksepi_diffusion_maxamp.defval = FMin(3, phygrd.xfs, phygrd.yfs, phygrd.zfs);
291 
292  } else {
293 
294  /* without increasing min TR for b < 1500, max diff amp seems to be ~50 mT/m (~70%) */
295  _ksepi_diffusion_maxamp.defval = 0.70 * FMin(3, phygrd.xfs, phygrd.yfs, phygrd.zfs);
296 
297  }
298  } else {
299 
300  /* by default, use 85% of physical max to allow for angled slices */
301  _ksepi_diffusion_maxamp.defval = 0.85 * FMin(3, phygrd.xfs, phygrd.yfs, phygrd.zfs);
302 
303  }
304 
305  ksepi_diffusion_maxamp = _ksepi_diffusion_maxamp.defval;
306 
307 
308  return SUCCESS;
309 }
Definition: KSFoundation.h:1948
float ksepi_diffusion_getmaxb()
Definition: ksepi_implementation_diffusion.e:146
#define HAVE_PREMIER_GRADIENTS
Definition: KSFoundation.h:167
int32_t i
Definition: KSFoundation_tgt.c:1389
PHYS_GRAD phygrd
float ksepi_diffusion_maxamp
Definition: ksepi_implementation_diffusion.e:58
Definition: KSFoundation.h:1945
float ks_gheatfact
Definition: GERequired.e:244
int ksepi_imsize
Definition: ksepi_implementation.e:176

◆ ksepi_diffusion_eval_UI()

STATUS ksepi_diffusion_eval_UI ( )
315  {
316  int i, b, j;
317  STATUS status;
318  DIFFSCHEME diffscheme_norm1;
319 
320  if (opdiffuse != KS_EPI_DIFFUSION_ON) {
321  return SUCCESS;
322  }
323 
324 
325  /* clear diffusion scheme table */
326  for (i = 0; i < MAX_DIFSCHEME_LENGTH; i++) {
327  diffscheme[0][i] = diffscheme[1][i] = diffscheme[2][i] = 0.0;
328  diffscheme_norm1[0][i] = diffscheme_norm1[1][i] = diffscheme_norm1[2][i] = 0.0;
329  }
330 
331 #ifdef PSD_HW
332  {
333  float maxb = ksepi_diffusion_getmaxb();
334  if (existcv(opnumbvals) && maxb > 0) {
335  opbval = maxb;
336  }
337  }
338 #else
339  /* In SIM (WTools), we let opbval set bvalstab[] since we are in simulation and can't access bvalstab[] in EvalTool
340  If opnumbvals > 1, we make the bvalstab[] a linearly increasing function of opbval with
341  bvalstab[opnumbvals-1] = opbval */
342  for (i = 0; i < opnumbvals; i++) {
343  bvalstab[i] = (i + 1.0) / ((float) opnumbvals) * opbval;
344  }
345 #endif
346 
347  /* Diffusion direction menu */
348  pidifrecnub = FALSE; /* but on for opdfaxall */
349  cvmax(opdifnumdirs, MAX_DIFSCHEME_LENGTH);
350 
351 
352  if (opdfaxall) {
353  pidifrecnub = TRUE;
354  ndiffdirs = 3;
355 
356  for (i = 0; i < ndiffdirs; i++) {
357  diffscheme[i][opdifnumt2 + i] = 1; /* X, Y, Z */
358  }
359 
360  } else if (opdfax3in1) {
361 
362  return ks_error("%s: 3in1 is not yet supported", __FUNCTION__);
363 
364  } else if (opdfaxtetra) {
365 
366  return ks_error("%s: TETRA is not yet supported", __FUNCTION__);
367 
368  } else if (optensor) {
369 
370  if (existcv(opdifnumdirs)) {
371  /* we need to rely on number of diffusion directions via 'ndiffdirs' instead of opdifnumdirs (which is
372  the value given by the menu) at a time when opdifnumdirs' existflag is set. Later in ksepi_diffusion_predownload_setrecon(),
373  if we are doing optensor with multiple b-values, we need to change opdifnumdirs to = opnumbvals * ndiffdirs, and
374  at the same time unset the existflag of opdifnumdirs.
375  This, since GE does not yet support multi-bvalues for optensor mode, and because the integrated ref scan recon of the
376  DTI data unfortunately checks for opdifnumdirs instead of rhnumdifdirs.
377  Here, we MUST here check for the existance of opdifnumdirs to avoid recursion when cveval() (and this function) is executed
378  after predownload before scanning. */
379  ndiffdirs = opdifnumdirs;
380  }
381 
382  /* avoid problems if ndiffdirs = 0 before #directions has been chosen by setting it to 6 */
383  if (ndiffdirs == 0)
384  ndiffdirs = 6;
385 
386  status = ksepi_diffusion_readtensorfile(diffscheme, opdifnumt2, ndiffdirs);
387  if (status != SUCCESS) return status;
388 
389  } else {
390  ndiffdirs = 1;
391 
392  /* One diffusion direction (default if none of above matches) */
393  /* cvoverride(opdifnumdirs, 1, PSD_FIX_OFF, PSD_EXIST_ON); */
394  diffscheme[XGRAD][opdifnumt2] = (opdfaxx != 0);
395  diffscheme[YGRAD][opdifnumt2] = (opdfaxy != 0);
396  diffscheme[ZGRAD][opdifnumt2] = (opdfaxz != 0);
397 
398  /* if no opXXX CVs have been set yet (on MR scanner as the PSD loads), default to one direction in Z */
399  if (!existcv(opdfaxx) && !existcv(opdfaxy) && !existcv(opdfaxz))
400  diffscheme[ZGRAD][opdifnumt2] = 1;
401 
402  }
403 
404 
405  /* make sure all diffusion directions are normalized */
406  for (i = 0; i < ndiffdirs; i++) {
407  float dnorm = sqrt(
408  diffscheme[XGRAD][opdifnumt2 + i] * diffscheme[XGRAD][opdifnumt2 + i] +
409  diffscheme[YGRAD][opdifnumt2 + i] * diffscheme[YGRAD][opdifnumt2 + i] +
410  diffscheme[ZGRAD][opdifnumt2 + i] * diffscheme[ZGRAD][opdifnumt2 + i]);
411  if (dnorm <= 0.000001) {
412  return ks_error("%s: A diffusion direction has zero norm", __FUNCTION__);
413  }
414  diffscheme_norm1[XGRAD][opdifnumt2 + i] = diffscheme[XGRAD][opdifnumt2 + i] / dnorm;
415  diffscheme_norm1[YGRAD][opdifnumt2 + i] = diffscheme[YGRAD][opdifnumt2 + i] / dnorm;
416  diffscheme_norm1[ZGRAD][opdifnumt2 + i] = diffscheme[ZGRAD][opdifnumt2 + i] / dnorm;
417  }
418 
419  /* repeat and scale diffusion scheme for multiple b-values */
420  for (b = 0; b < opnumbvals; b++) {
421  /* The square-root of the b-value ratio is used to scale the diffusion gradients across b-values */
422  float gscale = pow( (float) bvalstab[b] / (float) opbval, 0.5);
423 
424  for (i = 0; i < ndiffdirs; i++) {
425  j = i + b * ndiffdirs;
426  diffscheme[XGRAD][opdifnumt2 + j] = diffscheme_norm1[XGRAD][opdifnumt2 + i] * gscale;
427  diffscheme[YGRAD][opdifnumt2 + j] = diffscheme_norm1[YGRAD][opdifnumt2 + i] * gscale;
428  diffscheme[ZGRAD][opdifnumt2 + j] = diffscheme_norm1[ZGRAD][opdifnumt2 + i] * gscale;
429  }
430  }
431 
432  /* Save number of volumes total in opfphases based on the length of the diffusion scheme.
433  Need to do this here, before we reach predownload() as opfphases is used as an input argument
434  to GEReq_predownload_setrecon_epi()->GEReq_predownload_setrecon_voldata(). */
435  opfphases = opdifnumt2 + opnumbvals * ndiffdirs;
436 
437  /* computing root mean sqare averaged diffusion amplitudes for heating calculations
438  Note that this is a highly simplified approach, accurate heating estimates can only be computed with pgen_on_host,
439  gratHeatMethod = 1 (not supported by KSFoundation at the moment since sequencer instructions are only created on IPG)
440 
441  Workflow for future implementation of pulsegen on host:
442  minseq --> minseqseg --> getCornerpoints --> analyze_gradients calls pulsegen but requires entrypoint calcPulseparams
443  calcPulseparams(AVERAGE_POWER) --> sets amplitudes to average
444  calcPulseparams(MAXIMUM_POWER) --> sets amplitudes to maximum
445  */
447 
448  /* write diffusion scheme out for debugging */
449  {
450  FILE *fp;
451 #ifdef PSD_HW
452  fp = fopen("/usr/g/mrraw/diffusionscheme.txt", "w");
453 #else
454  fp = fopen("./diffusionscheme.txt", "w");
455 #endif
456  fprintf(fp, "Max b-value (opbval): %d s/mm^2\n\n", opbval);
457  fprintf(fp, "b-values:\n");
458  for (i = 0; i < opnumbvals; i++) {
459  float gscale = pow( (float) bvalstab[i] / (float) opbval, 0.5);
460  fprintf(fp, "%.1f %.2f\n", bvalstab[i], gscale);
461  }
462  fprintf(fp, "\n");
463  for (i = 0; i < opfphases; i++) {
464  fprintf(fp, "%f\t%f\t%f\n", diffscheme[XGRAD][i], diffscheme[YGRAD][i], diffscheme[ZGRAD][i]);
465  }
466  fclose(fp);
467  }
468 
469  return SUCCESS;
470 }
DIFFSCHEME diffscheme
Definition: ksepi_implementation_diffusion.e:76
STATUS ksepi_diffusion_readtensorfile(DIFFSCHEME diffscheme, int nb0, int ndirs)
Definition: ksepi_implementation_diffusion.e:88
#define MAX_DIFSCHEME_LENGTH
Definition: ksepi_implementation_diffusion.e:36
float ksepi_diffusion_getmaxb()
Definition: ksepi_implementation_diffusion.e:146
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int32_t i
Definition: KSFoundation_tgt.c:1389
int ndiffdirs
Definition: ksepi_implementation_diffusion.e:77
float DIFFSCHEME[3][MAX_DIFSCHEME_LENGTH]
Definition: ksepi_implementation_diffusion.e:37
Definition: KSFoundation.h:1945
void ksepi_diffusion_set_heat_scaling(DIFFSCHEME diffscheme)
Definition: ksepi_implementation_diffusion.e:163

◆ SolveCubic()

void SolveCubic ( double  a,
double  b,
double  c,
double  d,
int *  nsol,
double *  x 
)
482 {
483  double a1 = b/a, a2 = c/a, a3 = d/a;
484  double Q = (a1*a1 - 3.0*a2)/9.0;
485  double R = (2.0*a1*a1*a1 - 9.0*a1*a2 + 27.0*a3)/54.0;
486  double R2_Q3 = R*R - Q*Q*Q;
487  double theta;
488 
489  if (R2_Q3 <= 0){
490  *nsol = 3;
491  theta = acos(R/sqrt(Q*Q*Q));
492  x[0] = -2.0 * sqrt(Q) * cos( theta/3.0) - a1/3.0;
493  x[1] = -2.0 * sqrt(Q) * cos( (theta+2.0*PI)/3.0) - a1/3.0;
494  x[2] = -2.0 * sqrt(Q) * cos( (theta+4.0*PI)/3.0) - a1/3.0;
495  } else {
496  *nsol = 1;
497  x[0] = pow( sqrt(R2_Q3) + fabs(R), 1/3.0);
498  x[0] += Q/x[0];
499  x[0] *= (R < 0.0) ? 1 : -1;
500  x[0] -= a1/3.0;
501  }
502 
503 }
uint8_t c[4]
Definition: KSFoundation_tgt.c:1388

◆ ksepi_diffusion_calcTE()

STATUS ksepi_diffusion_calcTE ( double *  TE_s,
int  exciso2end,
int  crsh1_half180,
int  half180_crsh2,
int  crsh3_half180,
int  half180_crsh4,
int  readout2echo,
int  ramptime,
float  G,
int  bval_desired,
int  dualspinechoflag 
)
510  {
511  double exciso2end_s = 1.0E-6 * RUP_GRD(exciso2end); /* [s] */
512  double crsh1_half180_s = 1.0E-6 * RUP_GRD(crsh1_half180); /* [s] */
513  double half180_crsh2_s = 1.0E-6 * RUP_GRD(half180_crsh2); /* [s] */
514  double crsh3_half180_s = 1.0E-6 * RUP_GRD(crsh3_half180); /* [s] */
515  double half180_crsh4_s = 1.0E-6 * RUP_GRD(half180_crsh4); /* [s] */
516  double readout2echo_s = 1.0E-6 * RUP_GRD(readout2echo); /* [s] */
517  double ramptime_s = 1.0E-6 * RUP_GRD(ramptime); /* [s] */
518  double fixedtime_s;
519  double gam_SI = (2 * PI * 42.58E6); /* [rad/(sT)] */
520  double G_SI = G / 100.0; /* [G/cm] -> [T/m] */
521  double sol[3];
522  int nsol;
523  double c0, c1, c2, c3, c0new;
524 
525  /* all double variables are in SI units (see genbvalcode.m for details on c0-c3 below) */
526 
527  if (dualspinechoflag) { /* 2x180 */
528 
529  fixedtime_s = FMax(2, exciso2end_s + crsh1_half180_s, half180_crsh4_s + readout2echo_s) + 2.0 * ramptime_s;
530 
531  c3 = 1.0 / 1.2E1;
532 
533  c2 = crsh3_half180_s * (-3.0 / 1.6E1) - exciso2end_s * (1.0 / 1.6E1) - fixedtime_s * (7.0 / 1.6E1) - half180_crsh2_s * (3.0 / 1.6E1) + half180_crsh4_s * (1.0 / 1.6E1) + ramptime_s * (1.0 / 4.0);
534 
535  c1 = crsh3_half180_s * fixedtime_s * (1.0 / 2.0) + crsh3_half180_s * half180_crsh2_s * (1.0 / 2.0) + exciso2end_s * fixedtime_s * (1.0 / 2.0) + fixedtime_s * half180_crsh2_s * (1.0 / 2.0) - fixedtime_s * half180_crsh4_s * (1.0 / 2.0) -
536  exciso2end_s * ramptime_s * (1.0 / 2.0) - fixedtime_s * ramptime_s * (1.0 / 2.0) + half180_crsh4_s * ramptime_s * (1.0 / 2.0) + (crsh3_half180_s * crsh3_half180_s) * (1.0 / 4.0) + (fixedtime_s * fixedtime_s) * (1.0 / 2.0) +
537  (half180_crsh2_s * half180_crsh2_s) * (1.0 / 4.0) - (ramptime_s * ramptime_s) * (1.0 / 1.2E1);
538 
539  c0 = (crsh3_half180_s * crsh3_half180_s) * fixedtime_s * (-1.0 / 2.0) - crsh3_half180_s * (half180_crsh2_s * half180_crsh2_s) * (1.0 / 4.0) - (crsh3_half180_s * crsh3_half180_s) * half180_crsh2_s * (1.0 / 4.0) - exciso2end_s * (fixedtime_s * fixedtime_s) -
540  fixedtime_s * (half180_crsh2_s * half180_crsh2_s) * (1.0 / 2.0) + (fixedtime_s * fixedtime_s) * half180_crsh4_s + crsh3_half180_s * (ramptime_s * ramptime_s) * (1.3E1 / 1.2E1) + (crsh3_half180_s * crsh3_half180_s) * ramptime_s * (1.0 / 4.0) -
541  exciso2end_s * (ramptime_s * ramptime_s) + fixedtime_s * (ramptime_s * ramptime_s) * (7.0 / 6.0) - (fixedtime_s * fixedtime_s) * ramptime_s + half180_crsh2_s * (ramptime_s * ramptime_s) * (1.3E1 / 1.2E1) + (half180_crsh2_s * half180_crsh2_s) * ramptime_s * (1.0 / 4.0) +
542  half180_crsh4_s * (ramptime_s * ramptime_s) - (crsh3_half180_s * crsh3_half180_s * crsh3_half180_s) * (1.0 / 1.2E1) + (fixedtime_s * fixedtime_s * fixedtime_s) * (1.0 / 3.0) - (half180_crsh2_s * half180_crsh2_s * half180_crsh2_s) * (1.0 / 1.2E1) +
543  (ramptime_s * ramptime_s * ramptime_s) * (1.0 / 1.5E1) - crsh3_half180_s * fixedtime_s * half180_crsh2_s - crsh3_half180_s * fixedtime_s * ramptime_s + crsh3_half180_s * half180_crsh2_s * ramptime_s * (1.0 / 2.0) + exciso2end_s * fixedtime_s * ramptime_s * 2.0 -
544  fixedtime_s * half180_crsh2_s * ramptime_s - fixedtime_s * half180_crsh4_s * ramptime_s * 2.0;
545 
546  } else { /* 1x180 */
547 
548  fixedtime_s = FMax(2, exciso2end_s + crsh1_half180_s, half180_crsh2_s + readout2echo_s) + 2.0 * ramptime_s;
549 
550  c3 = 1.0 / 12.0;
551 
552  c2 = -(exciso2end_s + fixedtime_s - half180_crsh2_s - ramptime_s) / 4.0;
553 
554  c1 = exciso2end_s * fixedtime_s - fixedtime_s * half180_crsh2_s - exciso2end_s * ramptime_s + half180_crsh2_s * ramptime_s - ramptime_s * ramptime_s / 12.0;
555 
556  c0 = (fixedtime_s * fixedtime_s) * half180_crsh2_s - exciso2end_s * (fixedtime_s * fixedtime_s) - exciso2end_s * (ramptime_s * ramptime_s) +
557  (7 * fixedtime_s * (ramptime_s * ramptime_s)) / 6 - (fixedtime_s * fixedtime_s) * ramptime_s + half180_crsh2_s * (ramptime_s * ramptime_s) +
558  (fixedtime_s * fixedtime_s * fixedtime_s) / 3 - (7 * (ramptime_s * ramptime_s * ramptime_s)) / 15 + 2 * exciso2end_s * fixedtime_s * ramptime_s - 2 * fixedtime_s * half180_crsh2_s * ramptime_s;
559 
560  }
561 
562  /* bval = 1.0E-6 * gam_SI * gam_SI * G_SI * G_SI * (c3 * pow(TE_s, 3.0) + c2 * pow(TE_s, 2.0) + c1 * TE_s + c0); leading 1.0E-6 makes bval in s/mm^2 (e.g. b = 1000)
563  where
564  double gam_SI = (2 * PI * 42.58E6); [rad/(sT)]
565  double G_SI = G [G/cm] / 100.0; [T/m]
566 
567  b(TE_s) = 1.0E-6 * gam_SI * gam_SI * G_SI * G_SI * (c3 * pow(TE_s, 3.0) + c2 * pow(TE_s, 2.0) + c1 * TE_s + c0); [s/mm^2]
568  desired b-value: bval_desired; [s/mm^2]
569  F(TE_s) = b(TE_s) - bval_desired
570  Find TE_s that gives F(TE_s) = 0 => TE_s that will yield the correct b-value
571  F(TE_s) = 1.0E-6 * gam_SI * gam_SI * G_SI * G_SI * (c3 * pow(TE_s, 3.0) + c2 * pow(TE_s, 2.0) + c1 * TE_s + c0) - bval_desired = 0
572  =>
573  F(TE_s) = 1.0E-6 * gam_SI * gam_SI * G_SI * G_SI * (c3 * pow(TE_s, 3.0) + c2 * pow(TE_s, 2.0) + c1 * TE_s + (c0 - bval_desired/(1.0E-6 * gam_SI * gam_SI * G_SI * G_SI)))
574  => [divide leading factors and make a new c0new = c0 - bval_desired/(1.0E-6 * gam_SI * gam_SI * G_SI * G_SI)
575  Fnew(TE_s) = c3 * pow(TE_s, 3.0) + c2 * pow(TE_s, 2.0) + c1 * TE_s + c0new
576  Put in c3, c2, c1, c0new into SolveCubic function to get TE_s where F(TE_s) = 0
577  */
578  c0new = c0 - (double) bval_desired / (1.0E-6 * gam_SI * gam_SI * G_SI * G_SI);
579 
580  /* Solve cubic function in TE */
581  SolveCubic(c3, c2, c1, c0new, &nsol, sol);
582 
583  if (nsol == 3)
584  *TE_s = FMax(3, sol[0], sol[1], sol[2]);
585  else
586  *TE_s = sol[0];
587 
588 
589  return SUCCESS;
590 }
void SolveCubic(double a, double b, double c, double d, int *nsol, double *x)
Definition: ksepi_implementation_diffusion.e:476

◆ ksepi_diffusion_eval_gradients_TE()

STATUS ksepi_diffusion_eval_gradients_TE ( KSEPI_SEQUENCE ksepi)
604  {
605  double TE_s;
606  int exciso2end = ksepi->selrfexc.rf.iso2end + KS_RFSSP_POSTTIME + ksepi->selrfexc.grad.ramptime + ksepi->selrfexc.postgrad.duration; /* RF excitation isocenter to end of exc rephaser [us] */
607  int crsh1_half180 = ksepi->selrfref.pregrad.duration + KS_RFSSP_PRETIME + ksepi->selrfref.grad.ramptime + ksepi->selrfref.rf.start2iso; /* left crusher start to RF isocenter of 1st/only 180 [us] */
608  int half180_crsh2 = ksepi->selrfref.rf.iso2end + ksepi->selrfref.grad.ramptime + KS_RFSSP_POSTTIME + ksepi->selrfref.postgrad.duration; /* RF isocenter to end of right crusher of 1st/only 180 [us] */
609  int crsh3_half180 = 0; /* left crusher start to RF isocenter of 2nd 180 (opdualspinecho only) [us] */
610  int half180_crsh4 = 0; /* RF isocenter to end of right crusher of 2nd 180 (opdualspinecho only) [us] */
611  int fixedtime = 0;
612  int bvalue_validated = FALSE;
613  int remaining_attempts = 30;
614 
615  /* Clear both trap objects */
618 
619  if (ksepi_reflines > 0) {
620  exciso2end += ksepi->dynreftrain.duration;
621  if (ksepi_slicecheck == FALSE) { /* reflines dephaser may overlap with selrf rephaser unless slicecheck mode */
623  }
624  }
625 
626  if (opdiffuse != KS_EPI_DIFFUSION_ON) {
627  return SUCCESS;
628  }
629 
630  /* Diffusion amplitude to start out with [G/cm]. May decrease if b-value very small */
631  _ksepi_diffusion_amp.fixedflag = 0;
633 
634  /* Round the diffusion ramp time to nearest 4 us */
635  cvoverride(ksepi_diffusion_ramptime, RUP_GRD(ksepi_diffusion_ramptime), _ksepi_diffusion_ramptime.fixedflag, _ksepi_diffusion_ramptime.existflag);
636 
637  if (opdualspinecho) {
640  fixedtime = IMax(2, exciso2end + crsh1_half180, half180_crsh4 + ksepi->pre_delay.duration + ksepi->epitrain.time2center) + 2 * ksepi_diffusion_ramptime;
641  } else {
642  fixedtime = IMax(2, exciso2end + crsh1_half180, half180_crsh2 + ksepi->pre_delay.duration + ksepi->epitrain.time2center) + 2 * ksepi_diffusion_ramptime;
643  }
644  fixedtime = RUP_GRD(fixedtime);
645 
646 
647 
648  while (bvalue_validated == FALSE) {
649 
651  &TE_s, exciso2end /* [us] */, crsh1_half180 /* [us] */, half180_crsh2 /* [us] */, crsh3_half180 /* [us] */,
652  half180_crsh4 /* [us] */, ksepi->epitrain.time2center /* [us] */, ksepi_diffusion_ramptime /* [us] */,
653  ksepi_diffusion_amp /* [G/cm] */, opbval /* [s/mm^2] */, opdualspinecho) == FAILURE) {
654  return FAILURE;
655  }
656 
657  /* Save the TE found to the CV for later verification. ksepi_diffusion_echotime in [us] */
658  cvoverride(ksepi_diffusion_echotime, (TE_s * 1E6), PSD_FIX_OFF, PSD_EXIST_OFF);
660 
661  if (opdualspinecho) {
662  /* Set diffusion plateau times based on found TE */
663  ksepi->diffgrad.plateautime = RDN_GRD(ksepi_diffusion_echotime / 4 - fixedtime);
664  ksepi->diffgrad2.plateautime = RDN_GRD((ksepi_diffusion_echotime / 2 - half180_crsh2 - crsh3_half180 - 4 * ksepi_diffusion_ramptime) / 2);
665 
666  if ((ksepi->diffgrad.plateautime >= (2 * GRAD_UPDATE_TIME)) && (ksepi->diffgrad2.plateautime >= (2 * GRAD_UPDATE_TIME))) {
667  bvalue_validated = TRUE;
668  }
669 
670  /* Build up the trap object(s) manually, now that we know the plateau time(s) */
671  ksepi->diffgrad.amp = ksepi_diffusion_amp; /* [G/cm] */
672  ksepi->diffgrad2.amp = ksepi_diffusion_amp; /* [G/cm] */
675  strcpy(ksepi->diffgrad.description, "diffgrad1_4");
676  strcpy(ksepi->diffgrad2.description, "diffgrad2_3");
677  } else {
678  /* Set diffusion plateau times based on found TE */
679  ksepi->diffgrad.plateautime = RDN_GRD(ksepi_diffusion_echotime / 2 - fixedtime);
680 
681  if (ksepi->diffgrad.plateautime >= (2 * GRAD_UPDATE_TIME)) {
682  bvalue_validated = TRUE;
683  }
684 
685  /* Build up the trap object(s) manually, now that we know the plateau time(s) */
686  ksepi->diffgrad.amp = ksepi_diffusion_amp; /* [G/cm] */
688  strcpy(ksepi->diffgrad.description, "diffgrad");
689  }
690 
691  if (bvalue_validated == FALSE) {
692  /* Too low b-value or long ramptimes leading to negative plateau times?
693  Reduce diffusion gradient amplitude and try again */
694  ksepi_diffusion_amp *= 0.95;
695  remaining_attempts--;
696  if (remaining_attempts < 0) {
697  return ks_error("%s: TE => negative diffusion gradient plateau time", __FUNCTION__);
698  }
699  }
700  }
701 
702  /* duration and are are consequences of the fields just set (N.B. all are initialized to zero by ks_init_trap()) */
707 
708 
709  if (ksepi_diffusion_heat_avg == PSD_ON) {
713  if (opdualspinecho) {
717  }
718  } else {
719 
720  }
721 
722 
723  return SUCCESS;
724 }
int plateautime
Definition: KSFoundation.h:584
KS_TRAP grad
Definition: KSFoundation.h:1491
float ksepi_diffusion_scaleZ_heatcal
Definition: ksepi_implementation_diffusion.e:63
int ksepi_diffusion_echotime
Definition: ksepi_implementation_diffusion.e:64
float heat_scaling_factor[3]
Definition: KSFoundation.h:588
int start2iso
Definition: KSFoundation.h:944
STATUS ksepi_diffusion_calcTE(double *TE_s, int exciso2end, int crsh1_half180, int half180_crsh2, int crsh3_half180, int half180_crsh4, int readout2echo, int ramptime, float G, int bval_desired, int dualspinechoflag)
Definition: ksepi_implementation_diffusion.e:509
KS_SELRF selrfexc
Definition: ksepi_implementation.e:53
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
KS_EPI dynreftrain
Definition: ksepi_implementation.e:51
float ksepi_diffusion_maxamp
Definition: ksepi_implementation_diffusion.e:58
float ksepi_diffusion_scaleX_heatcal
Definition: ksepi_implementation_diffusion.e:61
KS_EPI epitrain
Definition: ksepi_implementation.e:50
KS_TRAP pregrad
Definition: KSFoundation.h:1490
int duration
Definition: KSFoundation.h:1845
#define KS_RFSSP_POSTTIME
Definition: KSFoundation.h:153
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
KS_SELRF selrfref
Definition: ksepi_implementation.e:54
Definition: KSFoundation.h:1945
int duration
Definition: KSFoundation.h:459
float area
Definition: KSFoundation.h:582
float amp
Definition: KSFoundation.h:581
KS_TRAP postgrad
Definition: KSFoundation.h:1492
int iso2end
Definition: KSFoundation.h:945
KS_DESCRIPTION description
Definition: KSFoundation.h:580
int time2center
Definition: KSFoundation.h:1846
KS_TRAP readphaser
Definition: KSFoundation.h:1838
KS_TRAP diffgrad
Definition: ksepi_implementation.e:56
int ksepi_reflines
Definition: ksepi_implementation.e:162
float ksepi_diffusion_scaleY_heatcal
Definition: ksepi_implementation_diffusion.e:62
KS_TRAP diffgrad2
Definition: ksepi_implementation.e:57
KS_SELRF selrfref2
Definition: ksepi_implementation.e:55
int ksepi_diffusion_ramptime
Definition: ksepi_implementation_diffusion.e:57
int duration
Definition: KSFoundation.h:585
int ksepi_slicecheck
Definition: ksepi_implementation.e:109
float ksepi_diffusion_amp
Definition: ksepi_implementation_diffusion.e:59
KS_WAIT pre_delay
Definition: ksepi_implementation.e:58
int ramptime
Definition: KSFoundation.h:583
int ksepi_diffusion_heat_avg
Definition: ksepi_implementation_diffusion.e:60
#define KS_RFSSP_PRETIME
Definition: KSFoundation.h:152

◆ ksepi_diffusion_predownload_setrecon()

STATUS ksepi_diffusion_predownload_setrecon ( )
729  {
730 
731  if (opdiffuse != KS_EPI_DIFFUSION_ON) {
732  return SUCCESS;
733  }
734 
735 
736  /* enforced copying of diffusion related opXXX to rhXXX */
737  cvoverride(rhnumbvals, opnumbvals, PSD_FIX_ON, PSD_EXIST_ON);
738 
739 
740  /* mimic GE, but not sure these are needed */
741  rhapp_option = opdifproctype; /* does this ever change from 0 ? */
742 
743  /* opuser 20-25 will be used by GE's DTI feature, but is also good to know for non-tensor
744  * for custom off-line DWI recons.
745  * rhuser 20,21,22 will be set by recon after reading in tensor.dat
746  * 20,21,22 represent the diffusion direction coeffs
747  */
748  opuser23 = opdifnumt2;
749  opuser24 = ndiffdirs;
750  rhuser23 = opdifnumt2; /* rhuser 23 and 24 needed by recon to read tensor.dat */
751  rhuser24 = ndiffdirs;
752  opuser25 = opdualspinecho;
753 
754  rhnumdifdirs = (ndiffdirs > 1) ? ndiffdirs : 1;
755 
756  if (optensor) {
757 
758  rhdptype = 0;
759 
760  /* multi-bvalue (multi-shell DTI/HARDI) hack for optensor.
761  We need to trick GE's diffusion recon to believe we have opdifnumdirs = opnumbvals * ndiffdirs.
762  This does not enable the data to be procecced by e.g. GE's FuncTool when opnumbvals > 1, but will put the
763  images in the DB for use by external DTI/HARDI software */
764  if (opnumbvals > 1 && existcv(opdifnumdirs)) {
765  /* MUST make the existflag for opdifnumdirs = 0 here to avoid circular evaluation on HOST
766  by calling ksepi_eval_diffusion_UI() and predownload multiple times */
767  cvoverride(opdifnumdirs, opnumbvals * ndiffdirs, PSD_FIX_OFF, PSD_EXIST_OFF); /* Don't change PSD_EXIST_OFF */
768  }
769 
770  opuser_usage_tag = DTI_PROC;
771  rhuser_usage_tag = DTI_PROC;
772 
773  } else {
774 
775 
776  opuser_usage_tag = 0;
777  rhuser_usage_tag = 0;
778 
779  /* non-tensor */
780  if (opsavedf == 1)
781  rhdptype = 1;
782  else if (opsavedf == 2)
783  rhdptype = 3;
784 
785  }
786 
787  return SUCCESS;
788 }
int ndiffdirs
Definition: ksepi_implementation_diffusion.e:77
Definition: KSFoundation.h:1945

◆ ksepi_diffusion_pg()

STATUS ksepi_diffusion_pg ( KSEPI_SEQUENCE ksepi,
int  TE 
)
795  {
796  KS_SEQLOC tmploc = KS_INIT_SEQLOC;
797  int i;
798 
799  if (opdiffuse != KS_EPI_DIFFUSION_ON) {
800  return SUCCESS;
801  }
802 
803  /* First diffusion gradient right after the excitation and any reference lines */
804  tmploc.ampscale = 1.0;
806 
807  if (ksepi_slicecheck == FALSE) { /* reflines dephaser may overlap with selrf rephaser unless slicecheck mode */
809  }
810 
811  if (ksepi_reflines>0) {
812  tmploc.pos += ksepi->dynreftrain.duration;
813  }
814 
815  for (i = XGRAD; i <= ZGRAD; i++) {
816  tmploc.board = i;
817  if (ks_pg_trap(&ksepi->diffgrad, tmploc, &ksepi->seqctrl) == FAILURE)
818  return FAILURE;
819  }
820 
821  /* Selective RF Refocus with left (pregrad.) and right (postgrad.) crushers */
822  if (opdualspinecho) {
823 
824  tmploc.board = ZGRAD;
826  if (ks_pg_selrf(&ksepi->selrfref, tmploc, &ksepi->seqctrl) == FAILURE)
827  return FAILURE;
828 
829  /* opdualspinecho: Second diffusion gradient after the 1st refocusing pulse */
830  tmploc.ampscale = -1.0;
832  for (i = XGRAD; i <= ZGRAD; i++) {
833  tmploc.board = i;
834  if (ks_pg_trap(&ksepi->diffgrad2, tmploc, &ksepi->seqctrl) == FAILURE)
835  return FAILURE;
836  }
837 
838  /* opdualspinecho: Third diffusion gradient right after the second */
839  tmploc.ampscale = 1.0;
840  tmploc.pos += ksepi->diffgrad2.duration;
841  for (i = XGRAD; i <= ZGRAD; i++) {
842  tmploc.board = i;
843  if (ks_pg_trap(&ksepi->diffgrad2, tmploc, &ksepi->seqctrl) == FAILURE)
844  return FAILURE;
845  }
846 
847  tmploc.board = ZGRAD;
849  if (ks_pg_selrf(&ksepi->selrfref2, tmploc, &ksepi->seqctrl) == FAILURE)
850  return FAILURE;
851 
852  /* opdualspinecho: Fourth diffusion gradient after the 2nd refocusing pulse */
853  tmploc.ampscale = -1.0;
855  for (i = XGRAD; i <= ZGRAD; i++) {
856  tmploc.board = i;
857  if (ks_pg_trap(&ksepi->diffgrad, tmploc, &ksepi->seqctrl) == FAILURE)
858  return FAILURE;
859  }
860 
861  } else { /* Stejskal-Tanner diffusion */
862 
864  if (ks_pg_selrf(&ksepi->selrfref, tmploc, &ksepi->seqctrl) == FAILURE)
865  return FAILURE;
866 
867  /* Second diffusion gradient after the refocusing pulse */
868  tmploc.ampscale = 1.0;
870  for (i = XGRAD; i <= ZGRAD; i++) {
871  tmploc.board = i;
872  if (ks_pg_trap(&ksepi->diffgrad, tmploc, &ksepi->seqctrl) == FAILURE)
873  return FAILURE;
874  }
875 
876  }
877 
878  return SUCCESS;
879 }
KS_TRAP grad
Definition: KSFoundation.h:1491
int start2iso
Definition: KSFoundation.h:944
KS_SELRF selrfexc
Definition: ksepi_implementation.e:53
int pos
Definition: KSFoundation.h:389
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
int32_t i
Definition: KSFoundation_tgt.c:1389
KS_EPI dynreftrain
Definition: ksepi_implementation.e:51
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
float ampscale
Definition: KSFoundation.h:390
KS_TRAP pregrad
Definition: KSFoundation.h:1490
int duration
Definition: KSFoundation.h:1845
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:49
KS_RF rf
Definition: KSFoundation.h:1485
KS_SELRF selrfref
Definition: ksepi_implementation.e:54
Definition: KSFoundation.h:1945
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
typedef struct used as argument to ks_pg_*** functions to control where and when to place a sequence ...
Definition: KSFoundation.h:387
KS_TRAP postgrad
Definition: KSFoundation.h:1492
int iso2end
Definition: KSFoundation.h:945
KS_TRAP readphaser
Definition: KSFoundation.h:1838
KS_TRAP diffgrad
Definition: ksepi_implementation.e:56
int ksepi_reflines
Definition: ksepi_implementation.e:162
#define KS_INIT_SEQLOC
Definition: KSFoundation.h:208
KS_TRAP diffgrad2
Definition: ksepi_implementation.e:57
KS_SELRF selrfref2
Definition: ksepi_implementation.e:55
int duration
Definition: KSFoundation.h:585
int ksepi_slicecheck
Definition: ksepi_implementation.e:109
int ramptime
Definition: KSFoundation.h:583

◆ ksepi_diffusion_scan_diffamp()

void ksepi_diffusion_scan_diffamp ( KSEPI_SEQUENCE ksepi,
int  volindx 
)
882  {
883  int i;
884 
885  if (opdiffuse != KS_EPI_DIFFUSION_ON) {
886  return;
887  }
888 
889  /*
890  d: ksepi.diffgrad
891  d2: ksepi.diffgrad2 (opdualspinecho only)
892  #<x>: instance number <x>
893 
894  opdualspinecho = TRUE (Twice-refocused):
895  ========================================
896 
897  _d#0__ ____d2#3___
898  XGRAD __/ \___ / \___ ___
899  \___d2#0____/ \__d#3_/
900  _d#1__ ____d2#4___
901  YGRAD __/ \___ / \___ ___
902  \___d2#2____/ \__d#4_/
903  _d#2__ ____d2#5___
904  ZGRAD __/ \___ / \___ ___
905  \___d2#3____/ \__d#5_/
906 
907 
908  opdualspinecho = FALSE (Stejskal-Tanner):
909  =========================================
910 
911  _d#0__ _d#3__
912  XGRAD __/ \___/ \___
913  _d#1__ _d#4__
914  YGRAD __/ \___/ \___
915  _d#2__ _d#5__
916  ZGRAD __/ \___/ \___
917 
918  */
919 
920 
921  for (i = XGRAD; i <= ZGRAD; i++) {
922  float amp = (volindx >= 0) ? diffscheme[i][volindx] : 0; /* 0 if volindx < 0 */
923 
925  if (opdualspinecho) {
927  }
928  }
929 
930 
931 }
int volindx
Definition: ksfse_implementation.e:2849
DIFFSCHEME diffscheme
Definition: ksepi_implementation_diffusion.e:76
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:198
int32_t i
Definition: KSFoundation_tgt.c:1389
void ks_scan_trap_ampscale_slice(KS_TRAP *trap, int start, int skip, int count, float ampscale)
Updates the amplitude of a selection of instances of a KS_TRAP sequence object
Definition: KSFoundation_tgt.c:290
Definition: KSFoundation.h:1945
KS_TRAP diffgrad
Definition: ksepi_implementation.e:56
KS_TRAP diffgrad2
Definition: ksepi_implementation.e:57

Variable Documentation

◆ seqcollection

KS_SEQ_COLLECTION seqcollection

◆ ksepi_excthickness

float ksepi_excthickness = 0

◆ ksepi_gscalerfexc

float ksepi_gscalerfexc = 0.9 with {0.1, 3.0, 0.9, VIS, "Excitation slice thk scaling (< 1.0 thicker slice)",}

◆ ksepi_slicecheck

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

◆ ksepi_spoilerarea

float ksepi_spoilerarea = 3000.0 with {0.0, 10000.0, 3000.0, VIS, "ksepi ksepi.spoiler gradient area",}

◆ ksepi_rfspoiling

int ksepi_rfspoiling = 1 with {0, 1, 1, VIS, "Enable RF spoiling 1:on 0:off",}

◆ ksepi_fse90

int ksepi_fse90 = 0 with {0, 1, 0, VIS, "Use FSE90 instead of SPSP for non-fatsat",}

◆ ksepi_rf3Dopt

int ksepi_rf3Dopt = 0 with {0, 10, 0, VIS, "Choose optimized SPSP pulse for 3D [0:OFF]",}

◆ ksepi_kissoff_factor

float ksepi_kissoff_factor = 0.04 with {0, 1, 0.04, VIS, "Slice oversampling fraction on each side (3D)",}

◆ ksepi_crusherscale

float ksepi_crusherscale = 1.0 with { -20.0, 20.0, 1.0, VIS, "scaling of crusher gradient area",}

◆ ksepi_gscalerfref

float ksepi_gscalerfref = 0.9 with {0.1, 3.0, 0.9, VIS, "Refocusing slice thk scaling (< 1.0 thicker slice)",}

◆ ksepi_rampsampling

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

◆ ksepi_readlobegap

int ksepi_readlobegap = 0 with {0, 10ms, 0, VIS, "extra gap between readout lobes [us]",}

◆ ksepi_echogap

int ksepi_echogap = 0 with {0, 100ms, 0, VIS, "extra gap between EPI echoes [us]",}

◆ ksepi_readsign

int ksepi_readsign = 1 with { -1, 1, 1, VIS, "Readout polarity: +1/-1",}

◆ ksepi_readampmax

float ksepi_readampmax = 3.0 with {0.0, 5.0, 3.0, VIS, "Max grad amp for EPI readout lobes",}

◆ ksepi_sr

float ksepi_sr = 0.01 with {0.0, , 0.01, VIS, "EPI SR: amp/ramp [(G/cm) / us]",}

◆ ksepi_esp

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

◆ ksepi_blipsign

int ksepi_blipsign = KS_EPI_POSBLIPS with {KS_EPI_NEGBLIPS, KS_EPI_POSBLIPS, KS_EPI_POSBLIPS, VIS, "Blip polarity: +1/-1",}

◆ ksepi_echotime_shifting

int ksepi_echotime_shifting = 1 with {0, 1, 1, VIS, "Enable echo time shifting for multi shot",}

◆ ksepi_kynover

int ksepi_kynover = 24 with {KSEPI_MINHNOVER, 512, 24, VIS, "#extralines for MinTE",}

◆ ksepi_kznover

int ksepi_kznover = 0 with {0, 512, 0, VIS, "#extralines in kz",}

◆ ksepi_ky_R

int ksepi_ky_R = 1 with {1, 512, 1, VIS, "Acceleration in ky",}

◆ ksepi_kz_R

int ksepi_kz_R = 1 with {1, 512, 1, VIS, "Acceleration in kz",}

◆ ksepi_kz_nacslines

int ksepi_kz_nacslines = 16 with {0, 512, 16, VIS, "Number of acs lines in kz",}

◆ ksepi_caipi

int ksepi_caipi = 0 with {0, 512, 0, VIS, "CAIPIRINHA shift (affects 3D epi only. Set 0 for no CAIPI)",}

◆ ksepi_fcy

int ksepi_fcy = 1 with {0, 1, 0, VIS, "Flowcomp Y when opfcomp"}

◆ ksepi_fcz

int ksepi_fcz = 1 with {0, 1, 0, VIS, "Flowcomp Z when opfcomp"}

◆ ksepi_fleet

int ksepi_fleet = 0 with {0, 1, 0, VIS, "FLEET calibration volume [0:OFF 1:ON]",}

◆ ksepi_fleet_flip

float ksepi_fleet_flip = 15.0 with {0.1, 90.0, 15.0, VIS, "FLEET flip angle [deg]",}

◆ ksepi_fleet_dda

int ksepi_fleet_dda = 0 with {0, 200, 0, VIS, "Dummies for FLEET module",}

◆ ksepi_fleet_num_ky

int ksepi_fleet_num_ky = 36 with {1, 512, 36, VIS, "Number of ky encodes for FLEET module",}

◆ ksepi_fleet_num_kz

int ksepi_fleet_num_kz = 24 with {1, 512, 24, VIS, "Number of kz encodes for FLEET module (3D only)",}

◆ ksepi_reflines

int ksepi_reflines = 0 with {0, 96, 0, VIS, "Number of phase reference lines per shot",}

◆ ksepi_swi_returnmode

int ksepi_swi_returnmode = 0 with {0, 7, 0, VIS, "SWI recon 0:Off 1:Acq 2:SWI 4:SWIphase",}

◆ ksepi_pos_start

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

◆ ksepi_ssi_time

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

◆ ksepi_dda

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

◆ ksepi_debug

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

◆ ksepi_imsize

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

◆ ksepi_abort_on_kserror

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

◆ ksepi_ghostcorr

int ksepi_ghostcorr = 1 with {0, 1, 1, VIS, "Ghost correction [0:OFF 1:ON]",}

◆ ksepi_ref_nsegments

int ksepi_ref_nsegments = 1 with {1, 512, 1, VIS, "Number of kz segments in reference volume",}

◆ ksepi_multishot_control

int ksepi_multishot_control = KSEPI_MULTISHOT_B0VOLS with {KSEPI_MULTISHOT_OFF, KSEPI_MULTISHOT_B0VOLS, KSEPI_MULTISHOT_B0VOLS, VIS, "0:PI 1:All MulShot 2:1stMulShot 3:b0MulShot",}

◆ ksepi_epiqfact

float ksepi_epiqfact = 1.0 with {1.0, 10.0, 1.0, VIS, "Quetness factor for the EPI readout only",}

◆ ksepi

◆ ksepi_fleetseq

◆ ksepi_interechotime

int ksepi_interechotime = 0

◆ ksepi_echotime_shifting_shotdelay

float ksepi_echotime_shifting_shotdelay = 0

◆ ksepi_echotime_shifting_sumdelay

int ksepi_echotime_shifting_sumdelay = 0

◆ sequence_iopts

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

◆ rfspoiling_phase_counter

int rfspoiling_phase_counter = 0

◆ ksepi_diffusion_ramptime

int ksepi_diffusion_ramptime = 1500 with {300, 30ms, 1500, VIS, "Ramp times for diffusion gradients", }

◆ ksepi_diffusion_maxamp

float ksepi_diffusion_maxamp = 0.0 with {0.0, 7.0, 3.0, VIS, "Cap for diffusion gradient amplitude", }

◆ ksepi_diffusion_amp

float ksepi_diffusion_amp = 0.0 with {0.0, 7.0, 0.0, VIS, "View-only: Current diffusion gradient amplitude", }

◆ ksepi_diffusion_heat_avg

int ksepi_diffusion_heat_avg = 1 with {0, 1, 1, VIS, "Root mean sqared averaging diffusion amplitudes heat calculations", }

◆ ksepi_diffusion_scaleX_heatcal

float ksepi_diffusion_scaleX_heatcal = 1 with {0, 1, 1, VIS, "View-only: x diffusion gradient amplitude for heating calculations", }

◆ ksepi_diffusion_scaleY_heatcal

float ksepi_diffusion_scaleY_heatcal = 1 with {0, 1, 1, VIS, "View-only: y diffusion gradient amplitude for heating calculations", }

◆ ksepi_diffusion_scaleZ_heatcal

float ksepi_diffusion_scaleZ_heatcal = 1 with {0, 1, 1, VIS, "View-only: z diffusion gradient amplitude for heating calculations", }

◆ ksepi_diffusion_echotime

int ksepi_diffusion_echotime = 0 with {0, , 0, VIS, "View-only: Echo time necessary to meet the desired b-value", }

◆ ksepi_diffusion_2ndcrushfact

float ksepi_diffusion_2ndcrushfact = 2.0 with {0.1, 10.0, 2.0, VIS, "Scale factor for 2nd crusher for opdualspinecho",}

◆ ksepi_diffusion_returnmode

int ksepi_diffusion_returnmode = OFFLINE_DIFFRETURN_ALL with {OFFLINE_DIFFRETURN_ALL, 128, OFFLINE_DIFFRETURN_ALL, VIS, "Diff maps All:0 Acq:1 b0:2 DWI:4 ADC:8 Exp:16 FA:32 cFA:64",}

◆ diffscheme

DIFFSCHEME diffscheme

◆ ndiffdirs

int ndiffdirs = 6