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

Data Structures

struct  KSEPI_SEQUENCE
 
struct  KSEPI_FLEET_SEQUENCE
 
struct  KSEPI_METADATA
 

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 PLAY_FLEET   ((int) (!KS_3D_SELECTED && oparc && opaccel_ph_stride > 1)) /* conditions when to play FLEET */
 
#define OPUSER_PSDVERSION   opuser0
 
#define SHOW_RHRECON   use0
 
#define OPUSER_KYNOVER   opuser1
 
#define SHOW_KYNOVER   use1
 
#define OPUSER_BLIPSIGN   opuser2
 
#define SHOW_BLIPSIGN   use2
 
#define OPUSER_EPIREADOUTMODE   opuser4
 
#define SHOW_EPIREADOUTMODE   use4
 
#define OPUSER_FLEET_EPIREADOUTMODE   opuser5
 
#define SHOW_FLEET_EPIREADOUTMODE   use5
 
#define OPUSER6_DIFF_RETURNMODE   opuser6 /* opuser6 is checked in recon_ksepi2, so don't chance this */
 
#define SHOW_DIFF_RETURNMODE   use6
 
#define OPUSER7_SWI_RETURNMODE   opuser7 /* opuser7 is checked in recon_ksepi2, so don't chance this */
 
#define SHOW_SWI_READOUTMODE   use7
 
#define OPUSER_REFLINES   opuser9
 
#define SHOW_REFLINES   use9
 
#define OPUSER_KZACSLINES   opuser15
 
#define SHOW_KZACSLINES   use15
 
#define KSEPI_INIT_SEQUENCE   {KS_INIT_SEQ_CONTROL, KS_INIT_EPI, KS_INIT_EPI, KS_INIT_TRAP, KS_INIT_SELRF, KS_INIT_SELRF, {KS_INIT_TRAP}, KS_INIT_WAIT, KS_INIT_WAIT, KS_INIT_TRAP, KS_INIT_TRAP}
 
#define KSEPI_FLEET_INIT_SEQUENCE   {KS_INIT_SEQ_CONTROL, KS_INIT_EPI, KS_INIT_TRAP, KS_INIT_SELRF, KS_INIT_WAIT, KS_INIT_WAIT}
 
#define KSEPI_INIT_METADATA   {KSEPI_SEQINDEX_MAIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, KSEPI_SEQPART_EPITRAIN, KS_NOTSET, KS_NOTSET, 1}
 
#define KSEPI_PHASEENCODING_MEMORYPOOL_SIZE   25000
 
#define MAX_DIFFSCHEME_LENGTH   512
 
#define KSEPI_DIFFUSION_MAXBVALS   10
 
#define KSEPI_DIFFUSION_MAXBVALUE   20000
 

Enumerations

enum  KSEPI_SEQINDICES { KSEPI_SEQINDEX_MAIN, KSEPI_SEQINDEX_FLEET, KSEPI_SEQINDEX_MAIN_SPLITODDEVEN, KSEPI_SEQINDEX_FLEET_SPLITODDEVEN }
 
enum  KSEPI_SEQPARTS { KSEPI_SEQPART_EPITRAIN, KSEPI_SEQPART_DYNREFTRAIN, KSEPI_SEQPART_FIDNAV }
 
enum  ksepi_diffusion_return {
  DIFFRETURN_ALL = 0, DIFFRETURN_ACQUIRED = 1, DIFFRETURN_B0 = 2, DIFFRETURN_MEANDWI = 4,
  DIFFRETURN_MEANADC = 8, DIFFRETURN_EXPATT = 16, DIFFRETURN_FA = 32, 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)
 
KS_CORESLICETIME ksepi_scan_irslice (const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
 
KS_CORESLICETIME ksepi_scan_coreslice (const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
 
KS_CORESLICETIME ksepi_scan_coreslicegroup (const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
 
KS_CORESLICETIME ksepi_scan_fleet_coreslice (const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
 
void ksepi_scan_attach_metadata (KSEPI_SEQUENCE *seq, const KS_DYNAMIC_STATE *dynamic, uint8_t sequence_group)
 
void ksepi_dump_metadata (KSEPI_METADATA *metadata, const KS_DYNAMIC_STATE *dynamic)
 
STATUS ksepi_set_loop_control_design (KSSCAN_LOOP_CONTROL_DESIGN *loop_design, const KS_EPI *epitrain)
 
STATUS ksepi_scan_seqstate (SCAN_INFO slice_pos, KS_PHASEENCODING_COORD starting_coord, ks_enum_epiblipsign blipsign)
 
s64 ksepi_scan_scanloop ()
 
const KSSCAN_LOOP_CONTROLksepi_get_loop_ctrl ()
 
void ksepi_init_imagingoptions (void)
 
STATUS ksepi_init_UI (void)
 
STATUS ksepi_eval_UI ()
 
STATUS ksepi_eval_setuprf ()
 
STATUS ksepi_eval_setupfleet ()
 
STATUS ksepi_eval_setupobjects ()
 
STATUS ksepi_eval_TErange ()
 
void ksepi_set_kspace_design_forsat (KS_KSPACE_DESIGN *kdesign)
 
void ksepi_set_slicetiming_design (KS_SLICETIMING_DESIGN *slicetiming_design)
 
STATUS ksepi_set_inversion_loop_control_design (KSINV_LOOP_CONTROL_DESIGN *invloopctrl_design, const KS_EPI *epitrain)
 
STATUS ksepi_eval_inversion (KS_SEQ_COLLECTION *seqcollection)
 
STATUS ksepi_eval_sat (KS_SEQ_COLLECTION *seqcollection)
 
STATUS ksepi_gradheat_play (const INT max_encode_mode, int nargs, void **args)
 
STATUS ksepi_eval_loops (KS_SEQ_COLLECTION *seqcollection)
 
int ksepi_eval_ssitime ()
 
STATUS ksepi_eval_scantime (KS_SEQ_COLLECTION *seqcollection)
 
STATUS ksepi_update_UI ()
 
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_pos, KS_PHASEENCODING_COORD starting_coord, ks_enum_epiblipsign blipsign)
 
void ksepi_scan_rf_off ()
 
void ksepi_scan_attach_metadata (KS_EPI *epitrain, KS_EPI *dynreftrain, const KS_DYNAMIC_STATE *dynamic, uint8_t sequence_group)
 
STATUS ksepi_scan_init (void)
 
STATUS ksepi_scan_prescanloop (int nloops, int dda)
 
STATUS ksepi_diffusion_init_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 readout2echo, int ramptime, float G, int bval_desired)
 
STATUS ksepi_diffusion_eval_gradients_TE (KSEPI_SEQUENCE *epi, const KSDIFF_CONTROL *diff_ctrl)
 
STATUS ksepi_eval_diffusion (KSDIFF_CONTROL *diff_ctrl)
 
STATUS ksepi_diffusion_pg (KSEPI_SEQUENCE *epi, int TE)
 

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",}
 
float ksepi_kissoff_factor = 0.04 with {0, 1, 0.04, VIS, "Slice oversampling fraction on each side (3D)",}
 
float ksepi_rfstretch_exc = 1.0 with {0.1,10.0, 1.0, VIS, "RF excitation stretch factor"}
 
int ksepi_fastexc3D = TRUE with {FALSE, TRUE, TRUE, VIS, "Sel. RF exc (3D) 0:EXC_SPSP_3D 1:EXC_FAST_SPSP_3D",}
 
float ksepi_crusher_dephasing = 6.0 with { 0.0, 100.0, 6.0, VIS, "crusher dephasing over slice [cycles]",}
 
float ksepi_gscalerfref = 0.9 with {0.1, 3.0, 0.9, VIS, "Refocusing slice thk scaling (< 1.0 thicker slice)",}
 
float ksepi_rfstretch_ref = 1.0 with {0.1,10.0, 1.0, VIS, "RF refocusing stretch factor",}
 
int ksepi_bridgecrushers = FALSE with {FALSE, TRUE, FALSE, VIS, "Bridge RF ref crushers",}
 
int ksepi_t1value_to_null = T1_FAT_3T with {0, 5s, T1_FAT_3T, VIS, "T1 value to NULL [us]",}
 
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_kz_nacslines = 8 with {0, 64, 8, VIS, "#acslines in kz",}
 
int ksepi_caipi = 0 with {0, 512, 0, VIS, "CAIPIRINHA shift (affects 3D epi only. Set 0 for no CAIPI)",}
 
int ksepi_readout_mode = KS_EPI_BIPOLAR with {KS_EPI_BIPOLAR, KS_EPI_FLYBACK, KS_EPI_BIPOLAR, VIS, "EPI readout mode 0: bipolar 1:splitoddeven 2:flyback",}
 
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]",}
 
int ksepi_echotime_shifting_fleet = 1 with {0, 1, 1, VIS, "Enable echo time shifting for multi shot FLEET",}
 
float ksepi_fleet_flip = 5.0 with {1.0, 90.0, 5.0, VIS, "FLEET flip angle [deg]",}
 
int ksepi_fleet_dda = 3 with {1, 200, 3, VIS, "Dummies for FLEET module",}
 
int ksepi_fleet_num_ky = 48 with {32, 256, 48, VIS, "Number of ky encodes for FLEET module",}
 
int ksepi_fleet_readout_mode = KS_EPI_SPLITODDEVEN with {KS_EPI_BIPOLAR, KS_EPI_FLYBACK, KS_EPI_SPLITODDEVEN, VIS, "FLEET EPI readout mode 0: bipolar 1:splitoddeven 2:flyback",}
 
int ksepi_fleet_nshots = 3 with {1, 128, 3, VIS, "# shots for FLEET",}
 
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 {1, 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_ref_nsegments = 1 with {1, 512, 1, VIS, "Number of kz segments in reference volume",}
 
float ksepi_epiqfact = 1.0 with {1.0, 10.0, 1.0, VIS, "Quietness factor for the EPI readout only",}
 
int ksepi_recvgain_mode = RG_CAL_MODE_HIGH_FIXED with {RG_CAL_MODE_MIN, RG_CAL_MODE_MAX, RG_CAL_MODE_HIGH_FIXED, VIS, "RecvGain - 0:Measured 1:8 2:5 3:Max",}
 
int ksepi_metadump = 0
 
KSEPI_SEQUENCE ksepi = KSEPI_INIT_SEQUENCE
 
KSSCAN_LOOP_CONTROL ksepi_loopctrl = KSSCAN_INIT_LOOP_CONTROL
 
KSDIFF_CONTROL ksepi_diffctrl = KSDIFF_INIT_CONTROL
 
KSEPI_FLEET_SEQUENCE ksepi_fleetseq = KSEPI_FLEET_INIT_SEQUENCE
 
KSSCAN_LOOP_CONTROL ksepi_fleet_loopctrl = KSSCAN_INIT_LOOP_CONTROL
 
KSINV_MODULE ksepi_inv = KSINV_INIT_MODULE
 
KSINV_LOOP_CONTROL ksepi_inv_loopctrl = KSINV_INIT_LOOP_CONTROL
 
KS_PHASEENCODING_COORD ksepi_phaseencoding_memorypool [KSEPI_PHASEENCODING_MEMORYPOOL_SIZE] = {KS_INIT_PHASEENCODING_COORD}
 
int ksepi_interechotime = 0
 
float ksepi_echotime_shifting_shotdelay = 0.0
 
float ksepi_echotime_shifting_shotdelay_fleet = 0.0
 
int ksepi_echotime_shifting_sumdelay = 0
 
int ksepi_echotime_shifting_sumdelay_fleet = 0
 
KS_KSPACE_ACQ kacq = KS_INIT_KSPACE_ACQ
 
int sequence_iopts []
 
int rfspoiling_phase_counter = 0
 
float ksepi_diffusion_amp_scale = 1.0 with {0.0, 1.0, 1.0, VIS, "Cap for scaling factor of 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", }
 
int ksepi_diffusion_returnmode = DIFFRETURN_ALL with {DIFFRETURN_ALL, 128, DIFFRETURN_ALL, VIS, "Diff maps All:0 Acq:1 b0:2 DWI:4 ADC:8 Exp:16 FA:32 cFA:64",}
 
int ksepi_diffusion_minramptime = 1ms with {0, 20ms, 1ms, VIS, "Minimum diffusion ramp time. If 0: syslimits used",}
 

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

◆ PLAY_FLEET

#define PLAY_FLEET   ((int) (!KS_3D_SELECTED && oparc && opaccel_ph_stride > 1)) /* conditions when to play FLEET */

◆ OPUSER_PSDVERSION

#define OPUSER_PSDVERSION   opuser0

◆ SHOW_RHRECON

#define SHOW_RHRECON   use0

◆ OPUSER_KYNOVER

#define OPUSER_KYNOVER   opuser1

◆ SHOW_KYNOVER

#define SHOW_KYNOVER   use1

◆ OPUSER_BLIPSIGN

#define OPUSER_BLIPSIGN   opuser2

◆ SHOW_BLIPSIGN

#define SHOW_BLIPSIGN   use2

◆ OPUSER_EPIREADOUTMODE

#define OPUSER_EPIREADOUTMODE   opuser4

◆ SHOW_EPIREADOUTMODE

#define SHOW_EPIREADOUTMODE   use4

◆ OPUSER_FLEET_EPIREADOUTMODE

#define OPUSER_FLEET_EPIREADOUTMODE   opuser5

◆ SHOW_FLEET_EPIREADOUTMODE

#define SHOW_FLEET_EPIREADOUTMODE   use5

◆ OPUSER6_DIFF_RETURNMODE

#define OPUSER6_DIFF_RETURNMODE   opuser6 /* opuser6 is checked in recon_ksepi2, so don't chance this */

◆ SHOW_DIFF_RETURNMODE

#define SHOW_DIFF_RETURNMODE   use6

◆ OPUSER7_SWI_RETURNMODE

#define OPUSER7_SWI_RETURNMODE   opuser7 /* opuser7 is checked in recon_ksepi2, so don't chance this */

◆ SHOW_SWI_READOUTMODE

#define SHOW_SWI_READOUTMODE   use7

◆ OPUSER_REFLINES

#define OPUSER_REFLINES   opuser9

◆ SHOW_REFLINES

#define SHOW_REFLINES   use9

◆ OPUSER_KZACSLINES

#define OPUSER_KZACSLINES   opuser15

◆ SHOW_KZACSLINES

#define SHOW_KZACSLINES   use15

◆ KSEPI_INIT_SEQUENCE

◆ KSEPI_FLEET_INIT_SEQUENCE

#define KSEPI_FLEET_INIT_SEQUENCE   {KS_INIT_SEQ_CONTROL, KS_INIT_EPI, KS_INIT_TRAP, KS_INIT_SELRF, KS_INIT_WAIT, KS_INIT_WAIT}

◆ KSEPI_INIT_METADATA

#define KSEPI_INIT_METADATA   {KSEPI_SEQINDEX_MAIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, KSEPI_SEQPART_EPITRAIN, KS_NOTSET, KS_NOTSET, 1}

initialization values for KSEPI_METADATA

◆ KSEPI_PHASEENCODING_MEMORYPOOL_SIZE

#define KSEPI_PHASEENCODING_MEMORYPOOL_SIZE   25000

num elements allocated for unique phase encodes. For EPI, only the blipphaser's ky value goes in there (first ky line in EPI train)

◆ MAX_DIFFSCHEME_LENGTH

#define MAX_DIFFSCHEME_LENGTH   512

Maximum 512 diffusion directions (including b=0)

◆ KSEPI_DIFFUSION_MAXBVALS

#define KSEPI_DIFFUSION_MAXBVALS   10

10 different b-values > 0

◆ KSEPI_DIFFUSION_MAXBVALUE

#define KSEPI_DIFFUSION_MAXBVALUE   20000

Enumeration Type Documentation

◆ KSEPI_SEQINDICES

Enumerator
KSEPI_SEQINDEX_MAIN 
KSEPI_SEQINDEX_FLEET 
KSEPI_SEQINDEX_MAIN_SPLITODDEVEN 
KSEPI_SEQINDEX_FLEET_SPLITODDEVEN 
Definition: ksepi_implementation.e:125
Definition: ksepi_implementation.e:125
KSEPI_SEQINDICES
Definition: ksepi_implementation.e:125
Definition: ksepi_implementation.e:125
Definition: ksepi_implementation.e:125

◆ KSEPI_SEQPARTS

Enumerator
KSEPI_SEQPART_EPITRAIN 
KSEPI_SEQPART_DYNREFTRAIN 
KSEPI_SEQPART_FIDNAV 
Definition: ksepi_implementation.e:126
Definition: ksepi_implementation.e:126
Definition: ksepi_implementation.e:126
KSEPI_SEQPARTS
Definition: ksepi_implementation.e:126

◆ ksepi_diffusion_return

Enumerator
DIFFRETURN_ALL 
DIFFRETURN_ACQUIRED 
DIFFRETURN_B0 
DIFFRETURN_MEANDWI 
DIFFRETURN_MEANADC 
DIFFRETURN_EXPATT 
DIFFRETURN_FA 
DIFFRETURN_CFA 
Definition: ksepi_implementation_diffusion.e:41
Definition: ksepi_implementation_diffusion.e:41
ksepi_diffusion_return
Definition: ksepi_implementation_diffusion.e:41
Definition: ksepi_implementation_diffusion.e:41
Definition: ksepi_implementation_diffusion.e:41
Definition: ksepi_implementation_diffusion.e:41
Definition: ksepi_implementation_diffusion.e:41
Definition: ksepi_implementation_diffusion.e:41
Definition: ksepi_implementation_diffusion.e:41

Function Documentation

◆ cvinit()

STATUS cvinit ( void  )
88  {
89  STATUS status;
90 
91  obl_method = PSD_OBL_OPTIMAL;
92 
93  status = GEReq_cvinit();
94  KS_RAISE(status);
95 
96  /* reset debug file ./ks_debug.txt (SIM) or /usr/g/mrraw/ks_debug.txt (HW) */
97  ks_dbg_reset();
98 
99  /* Imaging Options buttons */
101 
102  /* Setup UI buttons */
103  status = ksepi_init_UI();
104  KS_RAISE(status);
105 
106  return SUCCESS;
107 
108 } /* cvinit() */
int obl_method
Definition: GERequired.e:262
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:400
#define KS_RAISE(status)
Definition: KSFoundation.h:190
void ks_dbg_reset()
Clear debug file content
Definition: KSFoundation_common.c:140
STATUS GEReq_cvinit(void)
Helper function to be called at the beginning of cvinit()
Definition: GERequired.e:3194
STATUS ksepi_init_UI(void)
Initial setup of user interface (UI) with default values for menus and fields
Definition: ksepi_implementation.e:505

◆ cveval()

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

◆ my_cveval()

STATUS my_cveval ( void  )
131  {
132  STATUS status;
133 
135 
136  /* Link the memory pool for the phase encoding plans */
139  KS_RAISE(status);
140 
141  status = GEReq_cveval();
142  KS_RAISE(status);
143 
144  /* User Interface updates & opuserCV sync */
145  status = ksepi_eval_UI();
146  KS_RAISE(status);
147 
148  /* Setup sequence objects */
149  status = ksepi_eval_setupobjects();
150  KS_RAISE(status);
151 
152  /* Calculate minimum (and maximum TE) */
153  status = ksepi_eval_TErange();
154  KS_RAISE(status);
155 
156  status = ksepi_pg(ksepi_pos_start);
157  KS_RAISE(status);
158 
160  KS_RAISE(status);
161 
162  /* Add the passpacket seqctrl to the seqcollection */
164  KS_RAISE(status);
165 
166 
167  /*--------- Begin: Additional sequence modules -----------*/
168 
169  /* FLEET */
170  if (ksepi_fleet) {
172  KS_RAISE(status);
173 
175  KS_RAISE(status);
176  }
177 
178  /* Sat */
179  status = ksepi_eval_sat(&seqcollection);
180  KS_RAISE(status);
181 
182  /* Inversion */
184  KS_RAISE(status);
185 
186 
187  /*--------- End: Additional sequence modules -----------*/
188 
189 
190  /* Scan loop setup, Min TR, #slices per TR, RF/gradient heating & SAR */
191  status = ksepi_eval_loops(&seqcollection);
192  KS_RAISE(status);
193 
194  /* RF scaling across sequence modules */
196  KS_RAISE(status);
197 
198  /* scan time */
200  KS_RAISE(status);
201 
202  return SUCCESS;
203 
204 } /* my_cveval() */
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:114
STATUS ksepi_eval_loops(KS_SEQ_COLLECTION *seqcollection)
Setup of scan loop control structs (main and FLEET sequences) after heating calculations
Definition: ksepi_implementation.e:1890
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
#define KSEPI_PHASEENCODING_MEMORYPOOL_SIZE
Definition: ksepi_implementation.e:309
STATUS ksepi_eval_sat(KS_SEQ_COLLECTION *seqcollection)
Set up of the KSSAT_MODULE kssat for graphical saturation in the UI
Definition: ksepi_implementation.e:1773
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:302
STATUS ksepi_eval_TErange()
Sets the min TE based on the durations of the sequence objects in KSEPI_SEQUENCE (ksepi)
Definition: ksepi_implementation.e:1337
STATUS ksepi_eval_scantime(KS_SEQ_COLLECTION *seqcollection)
Sets the scan time and SAR values in the UI and checks that the sequence is within hardware limits...
Definition: ksepi_implementation.e:2003
STATUS ks_eval_addtoseqcollection(KS_SEQ_COLLECTION *seqcollection, KS_SEQ_CONTROL *seqctrl) WARN_UNUSED_RESULT
Adds a sequence module (KS_SEQ_CONTROL) to the KS_SEQ_COLLECTION struct for later RF scaling and SAR ...
Definition: KSFoundation_host.c:207
KS_SEQ_CONTROL seqctrl_passpack
Definition: GERequired.e:248
STATUS ksepi_eval_UI()
Gets the current UI and checks for valid inputs
Definition: ksepi_implementation.e:924
STATUS ksepi_pg(int)
The ksepi (main) pulse sequence generation
Definition: ksepi_implementation.e:2318
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:91
void ks_init_seqcollection(KS_SEQ_COLLECTION *seqcollection)
Resets KS_SEQ_COLLECTION to its default value (KS_INIT_SEQ_COLLECTION)
Definition: KSFoundation_host.c:156
STATUS ksepi_eval_inversion(KS_SEQ_COLLECTION *seqcollection)
Setup and evaluation of KSINV_DESIGN and the creation of a KSINV_MODULE module for inversion recovery...
Definition: ksepi_implementation.e:1724
#define KS_RAISE(status)
Definition: KSFoundation.h:190
STATUS ks_phaseencoding_memorypool_init(KS_PHASEENCODING_COORD *entries, uint64_t size)
Internal use for correct migration of KS_PHASEENCODING_PLAN from HOST to TGT (IPG)
Definition: KSFoundation_common.c:580
int ksepi_pos_start
Definition: ksepi_implementation.e:271
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:82
KS_PHASEENCODING_COORD ksepi_phaseencoding_memorypool[KSEPI_PHASEENCODING_MEMORYPOOL_SIZE]
Definition: ksepi_implementation.e:310
STATUS ksepi_pg_fleet(int start_time)
The FLEET pulse sequence generation
Definition: ksepi_implementation.e:2519
int ksepi_fleet
Definition: ksepi_implementation.e:250
STATUS ksepi_eval_setupobjects()
Sets up all sequence objects for the main sequence module (KSEPI_SEQUENCE ksepi)
Definition: ksepi_implementation.e:1186
STATUS GEReq_cveval(void)
Helper function to be called at the beginning of cveval()
Definition: GERequired.e:3346
STATUS GEReq_eval_rfscaling(KS_SEQ_COLLECTION *seqcollection)
Performs RF scaling of all RF pulses in the KS_SEQ_COLLECTION and Prescan
Definition: GERequired.e:808

◆ cvcheck()

STATUS cvcheck ( void  )
213  {
214  STATUS status;
215 
216  status = my_cveval();
217  KS_RAISE(status);
218 
219  status = GEReq_cvcheck();
220  KS_RAISE(status);
221 
222  status = ksepi_update_UI();
223  KS_RAISE(status);
224 
226 
227  return SUCCESS;
228 
229 } /* cvcheck() */
int ksepi_abort_on_kserror
Definition: ksepi_implementation.e:276
STATUS GEReq_cvcheck(void)
Helper function to be called at the beginning of cvcheck()
Definition: GERequired.e:3430
#define KS_RAISE(status)
Definition: KSFoundation.h:190
int abort_on_kserror
Definition: KSFoundation_common.c:40
STATUS my_cveval(void)
Definition: ksepi.e:131
STATUS ksepi_update_UI()
Update variables for the UI and checks for out of bounds values
Definition: ksepi_implementation.e:2045

◆ predownload()

STATUS predownload ( void  )
237  {
238  STATUS status;
239 
240  status = GEReq_predownload();
241  KS_RAISE(status);
242 
243  const KSSCAN_LOOP_CONTROL *loop_control = ksepi_get_loop_ctrl(); /* returns the inversion or standard loop control depending on inversion*/
244 
245  status = GEReq_predownload_prescan_options((RG_CAL_MODE_E) ksepi_recvgain_mode);
246  KS_RAISE(status);
247 
248  /* Set filter slot # for SCAN, APS2, MPS2 */
252 
253  /* slice ordering */
254  /* The following GE globals must be set appropriately:
255  data_acq_order[], rsp_info[], rsprot[], rsptrigger[]. This is a must for a main pulse sequence */
256  if (existcv(opslquant)) {
257  if (opimode == PSD_2D) {
259  } else {
260  status = GEReq_predownload_store_sliceplan3D(opslquant, opvquant);
261  }
262  KS_RAISE(status);
263  }
264 
265  /* generic rh-vars setup */
266  rhnecho = opnecho + (ksepi_reflines > 0);
268  KS_RAISE(status);
269 
270  /* Sequence specific recon settings that have not been set correctly at this point */
271  status = ksepi_predownload_setrecon();
272  KS_RAISE(status);
273 
274  /* plotting of sequence modules and slice timing to disk */
276 
277  return SUCCESS;
278 
279 } /* 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:3036
STATUS GEReq_predownload_setfilter(FILTER_INFO *filt)
Definition: GERequired.e:1382
KS_SLICETIMING slicetiming
Definition: ksscan.h:192
int ksepi_recvgain_mode
Definition: ksepi_implementation.e:279
STATUS GEReq_predownload_store_sliceplan(KS_SLICE_PLAN slice_plan)
Sets mandatory global GE arrays for data acquisition
Definition: GERequired.e:1072
STATUS ksepi_predownload_plot(KS_SEQ_COLLECTION *seqcollection)
Plotting of sequence modules and slice timing in HTML files
Definition: ksepi_implementation.e:2160
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
KS_EPI dynreftrain
Definition: ksepi_implementation.e:93
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:302
STATUS ksepi_predownload_setrecon()
Last-resort function to override certain recon variables not set up correctly already
Definition: ksepi_implementation.e:2241
KS_EPI epitrain
Definition: ksepi_implementation.e:92
int duration
Definition: KSFoundation.h:1943
int ksepi_interechotime
Definition: ksepi_implementation.e:313
KS_READTRAP read
Definition: KSFoundation.h:1932
#define KS_RAISE(status)
Definition: KSFoundation.h:190
STATUS GEReq_predownload_prescan_options(RG_CAL_MODE_E rg_cal_mode)
Prescan options
Definition: GERequired.e:3124
Structure containing all the information to perform a standard scan loop
Definition: ksscan.h:184
int ksepi_blipsign
Definition: ksepi_implementation.e:233
STATUS GEReq_predownload_store_sliceplan3D(int slices_in_slab, int slabs)
Sets mandatory global GE arrays for data acquisition (3D imaging)
Definition: GERequired.e:1275
FILTER_INFO filt
Definition: KSFoundation.h:843
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:82
int ksepi_reflines
Definition: ksepi_implementation.e:261
KS_READ acq
Definition: KSFoundation.h:1549
const KSSCAN_LOOP_CONTROL * ksepi_get_loop_ctrl()
Function to automatically switch between inverision and standard loop control
Definition: ksepi_implementation.e:2300
KS_SLICE_PLAN slice_plan
Definition: ksscan.h:42
STATUS GEReq_predownload(void)
Helper function to be called at the beginning of predownload()
Definition: GERequired.e:3473
int ksepi_imsize
Definition: ksepi_implementation.e:275
KS_EPI epitrain
Definition: ksepi_implementation.e:115

◆ pulsegen()

STATUS pulsegen ( void  )
288  {
289 
291 
292  /* Link the memory pool for the phase encoding plans */
295 
296 
297  /* Main Pulse Sequence */
299  KS_SEQLENGTH(seqcore, ksepi.seqctrl);
300 
301  /* Sat */
302  if (kssat.seqctrl.duration > 0) {
303  kssat_pg(&kssat);
304  KS_SEQLENGTH(seqsat, kssat.seqctrl);
305  }
306 
307  /* Inversion sequence modules */
308  if (ANYINVERSION) {
310  KS_SEQLENGTH(seqinv, ksepi_inv.seqctrl);
311  KS_SEQLENGTH(seqtrfill, ksepi_inv_loopctrl.seqctrl_filltr); /* FLAIR BLOCK requires 2 sequence modules */
312  }
313 
314  /* FLEET module */
317 
319 
320  buildinstr(); /* load the sequencer memory */
321 
322 
323  return SUCCESS;
324 
325 } /* pulsegen() */
KS_SEQ_CONTROL seqctrl
Definition: kssat.e:53
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:114
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:297
STATUS kssat_pg(KSSAT_MODULE *sat)
Place all waveforms for the saturation module
Definition: kssat.e:180
#define KSEPI_PHASEENCODING_MEMORYPOOL_SIZE
Definition: ksepi_implementation.e:309
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:302
int duration
Definition: KSFoundation.h:1227
KSINV_LOOP_CONTROL ksepi_inv_loopctrl
Definition: ksepi_implementation.e:307
STATUS ksepi_pg(int)
The ksepi (main) pulse sequence generation
Definition: ksepi_implementation.e:2318
void GEReq_pulsegenEnd(void)
Helper function to be called at the end of pulsegen()
Definition: GERequired.e:3598
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:91
KSSAT_MODULE kssat
Definition: kssat.e:112
STATUS ksinv_pg(KSINV_MODULE *seq)
Generation of the waveforms for the waveform of the standard inversion module
Definition: ksinversion.cc:791
STATUS ks_phaseencoding_memorypool_init(KS_PHASEENCODING_COORD *entries, uint64_t size)
Internal use for correct migration of KS_PHASEENCODING_PLAN from HOST to TGT (IPG)
Definition: KSFoundation_common.c:580
int ksepi_pos_start
Definition: ksepi_implementation.e:271
KS_PHASEENCODING_COORD ksepi_phaseencoding_memorypool[KSEPI_PHASEENCODING_MEMORYPOOL_SIZE]
Definition: ksepi_implementation.e:310
#define ANYINVERSION
Definition: KSFoundation.h:346
STATUS ksepi_pg_fleet(int start_time)
The FLEET pulse sequence generation
Definition: ksepi_implementation.e:2519
KSINV_MODULE ksepi_inv
Definition: ksepi_implementation.e:306
KS_SEQ_CONTROL seqctrl_filltr
Definition: ksinversion.h:111
void GEReq_pulsegenBegin(void)
Helper function to be called at the beginning of pulsegen()
Definition: GERequired.e:3571
KS_SEQ_CONTROL seqctrl
Definition: ksinversion.h:73

◆ mps2()

STATUS mps2 ( void  )
348  {
349 
350  rspent = L_MPS2;
351  strcpy(psdexitarg.text_arg, "mps2");
352 
353  if (ksepi_scan_init() == FAILURE)
354  return rspexit();
355 
357 
358  rspexit();
359 
360  return SUCCESS;
361 
362 } /* 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:3239
int ksepi_dda
Definition: ksepi_implementation.e:273
STATUS ksepi_scan_prescanloop(int nloops, int dda)
Prescan loop called from both APS2 and MPS2 entry points
Definition: ksepi_implementation.e:3267
int rspent
Definition: GERequired.e:3712
PSD_EXIT_ARG psdexitarg

◆ aps2()

STATUS aps2 ( void  )
372  {
373 
374  rspent = L_APS2;
375  strcpy(psdexitarg.text_arg, "aps2");
376 
377  if (ksepi_scan_init() == FAILURE)
378  return rspexit();
379 
381 
382  rspexit();
383 
384  return SUCCESS;
385 
386 } /* 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:3239
int ksepi_dda
Definition: ksepi_implementation.e:273
STATUS ksepi_scan_prescanloop(int nloops, int dda)
Prescan loop called from both APS2 and MPS2 entry points
Definition: ksepi_implementation.e:3267
int rspent
Definition: GERequired.e:3712
PSD_EXIT_ARG psdexitarg

◆ scan()

STATUS scan ( void  )
397  {
398 
399  rspent = L_SCAN;
400  strcpy(psdexitarg.text_arg, "scan");
401 
402  if (ksepi_scan_init() == FAILURE)
403  return rspexit();
404 
406 
407  GEReq_endofscan();
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:3239
int GEReq_endofscan()
Sets SSP word in sequence off_GEpass() to tell system that scan is done
Definition: GERequired.e:3647
s64 ksepi_scan_scanloop()
Plays out all volumes and passes of a single or multi-pass scan
Definition: ksepi_implementation.e:3180
int rspent
Definition: GERequired.e:3712
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 
)

Evaluates the flow compensation gradient on the phase encoding (Y) board

This function computes the flow compensation gradient for the phase encoding (Y) board based on the EPI readout struct

Parameters
[out]fcphasePointer to the flow compensation KS_TRAP gradient on the Y board
[in]epiPointer to the KS_EPI structure containing the EPI parameters
[in]descDescription of the flow compensation phase gradients
Return values
STATUSSUCCESS or FAILURE
990  {
991 
992  /* set time origin at end of bipolar flow comp lobe/beginning of epi.blipphaser */
993  float dummy1 = 0.0;
994  float dummy2 = 0.0;
995  float zeromomentsum = 0.0;
996  float firstmomentsum = 0.0;
997  int pulsepos = 0;
998  int invertphase = 0;
999  int pulsecnt;
1000  int epiesp = 0;
1001 
1002  epiesp = (epi->read.grad.duration + epi->read_spacing);
1003 
1004  /* compute moments for blips */
1005  pulsepos = epi->blipphaser.grad.duration + epiesp - epi->blip.duration / 2;
1006 
1007  int blips2cent = ((epi->blipphaser.nover != 0) ? (epi->blipphaser.nover / epi->blipphaser.R) : (epi->etl / 2)) - 1;
1008 
1009  for (pulsecnt = 0; pulsecnt < blips2cent; pulsecnt++) {
1010  /* N.B.: pulsepos is updated in rampmoments() */
1011  rampmoments(0.0, epi->blip.amp, epi->blip.ramptime, invertphase, &pulsepos, &dummy1, &dummy2, &zeromomentsum, &firstmomentsum);
1012  rampmoments(epi->blip.amp, epi->blip.amp, epi->blip.plateautime, invertphase, &pulsepos, &dummy1, &dummy2, &zeromomentsum, &firstmomentsum);
1013  rampmoments(epi->blip.amp, 0.0, epi->blip.ramptime, invertphase, &pulsepos, &dummy1, &dummy2, &zeromomentsum, &firstmomentsum);
1014  pulsepos += (epiesp - epi->blip.duration);
1015  }
1016 
1017  ks_init_trap(fcphase);
1018 
1019  if (!areSame(zeromomentsum, 0) && !areSame(firstmomentsum, 0)) {
1020  int fcramp, fcplateau, dummy;
1021  float fcamp;
1022  amppwygmn(zeromomentsum, firstmomentsum, epi->blipphaser.grad.ramptime, epi->blipphaser.grad.plateautime, epi->blipphaser.grad.ramptime,
1023  0.0, 0.0, (double) ks_syslimits_ampmax(loggrd), (double) ks_syslimits_ramptimemax(loggrd), 0,
1024  &fcramp, &fcplateau, &dummy, &fcamp);
1025 
1026  fcphase->amp = fcamp;
1027  fcphase->ramptime = fcramp;
1028  fcphase->plateautime = fcplateau;
1029  fcphase->duration = 2 * fcphase->ramptime + fcphase->plateautime;
1030  fcphase->area = fcphase->duration * ((float) fcphase->ramptime + fcphase->plateautime);
1031  sprintf(fcphase->description, desc);
1032  }
1033 
1034  return SUCCESS;
1035 
1036 } /* ksepi_eval_flowcomp_phase() */
KS_TRAP blip
Definition: KSFoundation.h:1935
int plateautime
Definition: KSFoundation.h:672
int R
Definition: KSFoundation.h:1723
#define areSame(a, b)
Definition: KSFoundation.h:144
KS_TRAP grad
Definition: KSFoundation.h:1719
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:235
KS_PHASER blipphaser
Definition: KSFoundation.h:1937
KS_TRAP grad
Definition: KSFoundation.h:1561
int ks_syslimits_ramptimemax(LOG_GRAD loggrd)
Returns the minimum ramp time to get from zero to full gradient scale
Definition: KSFoundation_common.c:282
int etl
Definition: KSFoundation.h:1941
void ks_init_trap(KS_TRAP *trap)
Resets a KS_TRAP sequence object to its default value (KS_INIT_TRAP)
Definition: KSFoundation_host.c:62
LOG_GRAD loggrd
KS_READTRAP read
Definition: KSFoundation.h:1932
float area
Definition: KSFoundation.h:670
float amp
Definition: KSFoundation.h:669
int nover
Definition: KSFoundation.h:1722
KS_DESCRIPTION description
Definition: KSFoundation.h:668
int read_spacing
Definition: KSFoundation.h:1942
int duration
Definition: KSFoundation.h:673
int ramptime
Definition: KSFoundation.h:671

◆ ksepi_pg()

STATUS ksepi_pg ( int  start_time)

The ksepi (main) pulse sequence generation

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
2318  {
2319 
2320  STATUS status;
2321  KS_SEQLOC tmploc = KS_INIT_SEQLOC;
2322  int epi_startpos = KS_NOTSET;
2323  int epi_readout_startpos = KS_NOTSET;
2324  int fc_startpos = KS_NOTSET;
2325  int fcz_endpos = KS_NOTSET;
2326  int echo, board;
2327 
2328  if (start_time < KS_RFSSP_PRETIME) {
2329  return KS_THROW("1st arg (pos start) must be at least %d us", KS_RFSSP_PRETIME);
2330  }
2331 
2332 #ifdef HOST_TGT
2333  if (opte < avminte) {
2334  /* we cannot proceed until TE is in range.
2335  Return a long seq duration and pretend all is good */
2337  return SUCCESS;
2338  }
2339 #endif
2340 
2341 
2342  /*******************************************************************************************************
2343  * RF Excitation
2344  *******************************************************************************************************/
2345  tmploc.ampscale = 1.0;
2346  tmploc.pos = RUP_GRD(start_time + KS_RFSSP_PRETIME);
2347  tmploc.board = ZGRAD;
2348 
2349  /* N.B.: ks_pg_selrf()->ks_pg_rf() detects that ksepi.selrfexc is an excitation pulse
2350  (ksepi.selrfexc.rf.role = KS_RF_ROLE_EXC) and will also set ksepi.seqctrl.momentstart
2351  to the absolute position in [us] of the isocenter of the RF excitation pulse */
2352  status = ks_pg_selrf(&ksepi.selrfexc, tmploc, &ksepi.seqctrl);
2353  KS_RAISE(status);
2354 
2355  /* forward to end of selrfexc.postgrad (works for when slice sel gradient is KS_TRAP or KS_WAVE as only
2356  one of them can have non-zero duration at a given time) */
2358 
2359  /*******************************************************************************************************
2360  * Flow comp in slice dir
2361  *******************************************************************************************************/
2362 
2363  /* First flow comp gradient was already merged into selrf rephaser */
2364  /* Second flow comp gradient slice for slice excitation */
2365  status = ks_pg_trap(&ksepi.fcompslice, tmploc, &ksepi.seqctrl); /* N.B.: will return quietly if ksepi.fcompslice.duration = 0 (opfcomp = 0) */
2366  KS_RAISE(status);
2367  fcz_endpos = tmploc.pos + ksepi.fcompslice.duration;
2368 
2369  /*******************************************************************************************************
2370  * EPI phase reference lines
2371  *******************************************************************************************************/
2373  tmploc.pos = fcz_endpos;
2374  if (ksepi_slicecheck == FALSE) { /* reflines dephaser may overlap with slice flow comp and selrf rephaser unless slicecheck mode */
2376  }
2377  tmploc.ampscale = ksepi_readsign;
2378  status = ks_pg_epi(&ksepi.dynreftrain, tmploc, &ksepi.seqctrl);
2379  KS_RAISE(status);
2380 
2381  /*******************************************************************************************************
2382  * EPI trains: Begin (> 1 only supported with offline recon)
2383  -------------------------------------------------------------------------------------------------------*/
2384  for (echo = 0; echo < opnecho; echo++) {
2385 
2386  if (acq_type == TYPSPIN) {
2387  if (opdiffuse && echo == 0) {
2388  status = ksepi_diffusion_pg(&ksepi, opte);
2389  KS_RAISE(status);
2390  } else {
2391  if (echo == 0) /* RF refocusing pulse for 1st EPI train at TE/2 */
2393  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) */
2394  tmploc.pos = epi_startpos + ksepi.epitrain.duration + KS_RFSSP_PRETIME + ksepi_echogap / 2;
2395  tmploc.board = ZGRAD;
2396  status = ks_pg_selrf(&ksepi.selrfref, tmploc, &ksepi.seqctrl);
2397  KS_RAISE(status);
2398  }
2399  } /* acq_type == TYPSPIN */
2400 
2401  epi_startpos = ksepi.seqctrl.momentstart + opte - ksepi.epitrain.time2center + (echo * ksepi_interechotime);
2402  epi_readout_startpos = epi_startpos + IMax(3, ksepi.epitrain.readphaser.duration,
2405 
2406  /*******************************************************************************************************
2407  * Flow comp in phase dir
2408  *******************************************************************************************************/
2409  fc_startpos = epi_readout_startpos - ksepi.epitrain.blipphaser.grad.duration - 2 * ksepi.fcompphase.duration;
2410  tmploc.board = YGRAD;
2411  tmploc.pos = fc_startpos;
2412  tmploc.ampscale = 1;
2413  status = ks_pg_trap(&ksepi.fcompphase, tmploc, &ksepi.seqctrl); /* instance #0. N.B.: will return quietly if ksepi.fcompphase.duration = 0 */
2414  KS_RAISE(status);
2415 
2416  tmploc.pos += ksepi.fcompphase.duration;
2417  tmploc.ampscale = -1;
2418  status = ks_pg_trap(&ksepi.fcompphase, tmploc, &ksepi.seqctrl); /* instance #1 */
2419  KS_RAISE(status);
2420 
2421  /*******************************************************************************************************
2422  * EPI readout including de/rephasers on freq, phase and slice encoding axes (net zero moment on both axes)
2423  *******************************************************************************************************/
2425  tmploc.pos = epi_startpos;
2426  tmploc.ampscale = ksepi_readsign;
2427  status = ks_pg_epi(&ksepi.epitrain, tmploc, &ksepi.seqctrl);
2428  KS_RAISE(status);
2429 
2430  /*******************************************************************************************************
2431  * EPI echo time shifting pre_delay (only before 1st EPI train "echo = 0")
2432  *******************************************************************************************************/
2433  if (ksepi_echotime_shifting == TRUE && echo == 0) {
2434  for (board = XGRAD; board <= SSP; board++) {
2435  tmploc.board = board;
2436  if (oppseq == PSD_SE) {
2437  /* 2D: SE-EPI or DW-EPI */
2438  tmploc.pos = epi_startpos - GRAD_UPDATE_TIME;
2439  } else {
2440  /* 2D/3D: GE-EPI
2441  Place wait pulses just before main epi train dephasers (incl flowcomp if present) */
2442  if ((board == XGRAD && ksepi_slicecheck == FALSE) || (board == ZGRAD && ksepi_slicecheck == TRUE)) {
2443  tmploc.pos = epi_readout_startpos - ksepi.epitrain.readphaser.duration - GRAD_UPDATE_TIME;
2444  } else if (board == YGRAD) {
2445  tmploc.pos = fc_startpos - GRAD_UPDATE_TIME;
2446  } else {
2447  tmploc.pos = epi_readout_startpos - ksepi.epitrain.zphaser.grad.duration - GRAD_UPDATE_TIME;
2448  }
2449  }
2450  status = ks_pg_wait(&ksepi.pre_delay, tmploc, &ksepi.seqctrl);
2451  KS_RAISE(status);
2452  }
2453  }
2454 
2455  } /* for echo (= EPItrain) */
2456 
2457  /*------------------------------------------------------------------------------------------------------
2458  * EPI trains: End
2459  *******************************************************************************************************/
2460 
2461  /*******************************************************************************************************
2462  * Gradient spoilers on Y and Z (at the same time)
2463  *******************************************************************************************************/
2464  tmploc.ampscale = 1.0;
2465  tmploc.pos = epi_startpos + ksepi.epitrain.duration;
2466  tmploc.board = YGRAD;
2467  status = ks_pg_trap(&ksepi.spoiler, tmploc, &ksepi.seqctrl);
2468  KS_RAISE(status);
2469 
2470  tmploc.board = ZGRAD;
2471  status = ks_pg_trap(&ksepi.spoiler, tmploc, &ksepi.seqctrl);
2472  KS_RAISE(status);
2473 
2474  tmploc.pos += ksepi.spoiler.duration;
2475 
2476  /*******************************************************************************************************
2477  * EPI echo time shifting post_delay
2478  *******************************************************************************************************/
2479  if (ksepi_echotime_shifting == TRUE) {
2480  tmploc.pos += GRAD_UPDATE_TIME;
2481  tmploc.board = KS_ALL;
2482  status = ks_pg_wait(&ksepi.post_delay, tmploc, &ksepi.seqctrl);
2483  KS_RAISE(status);
2484  tmploc.pos += IMax(2, psd_grd_wait, psd_rf_wait) + GRAD_UPDATE_TIME;
2486  }
2487 
2488  /*******************************************************************************************************
2489  * Set the minimal sequence duration (ksepi.seqctrl.min_duration) by calling
2490  * ks_eval_seqctrl_setminduration()
2491  *******************************************************************************************************/
2492 
2493  /* make sure we are divisible by GRAD_UPDATE_TIME (4us) */
2494  tmploc.pos = RUP_GRD(tmploc.pos);
2495 
2496 #ifdef HOST_TGT
2497  /* 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() */
2499  ks_eval_seqctrl_setminduration(&ksepi.seqctrl, tmploc.pos); /* tmploc.pos now corresponds to the end of last gradient in the sequence */
2500 #endif
2501 
2502  return SUCCESS;
2503 
2504 } /* ksepi_pg() */
int ksepi_readsign
Definition: ksepi_implementation.e:225
Definition: KSFoundation.h:2319
KS_TRAP grad
Definition: KSFoundation.h:1463
int start2iso
Definition: KSFoundation.h:1032
KS_TRAP grad
Definition: KSFoundation.h:1719
KS_SELRF selrfexc
Definition: ksepi_implementation.e:95
int pos
Definition: KSFoundation.h:463
#define KS_NOTSET
Definition: KSFoundation.h:115
int ksepi_echotime_shifting
Definition: ksepi_implementation.e:234
KS_WAVE gradwave
Definition: KSFoundation.h:1465
int ksepi_eval_ssitime()
The SSI time for the sequence
Definition: ksepi_implementation.e:1965
KS_TRAP fcompphase
Definition: ksepi_implementation.e:100
KS_PHASER blipphaser
Definition: KSFoundation.h:1937
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
KS_EPI dynreftrain
Definition: ksepi_implementation.e:93
STATUS ks_pg_selrf(KS_SELRF *selrf, KS_SEQLOC loc, KS_SEQ_CONTROL *ctrl) WARN_UNUSED_RESULT
Places a KS_SELRF sequence object on a gradient (and RF) board at some position in the pulse sequence...
Definition: KSFoundation_common.c:2817
int momentstart
Definition: KSFoundation.h:1228
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:2889
int board
Definition: KSFoundation.h:462
KS_PHASER zphaser
Definition: KSFoundation.h:1938
Definition: KSFoundation.h:2324
float ampscale
Definition: KSFoundation.h:464
KS_EPI epitrain
Definition: ksepi_implementation.e:92
Definition: KSFoundation.h:2326
KS_TRAP pregrad
Definition: KSFoundation.h:1462
int duration
Definition: KSFoundation.h:1943
int ksepi_interechotime
Definition: ksepi_implementation.e:313
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:91
KS_RF rf
Definition: KSFoundation.h:1454
KS_SELRF selrfref
Definition: ksepi_implementation.e:96
KS_TRAP fcompslice
Definition: ksepi_implementation.e:101
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:3365
STATUS ks_pg_trap(KS_TRAP *trap, KS_SEQLOC loc, KS_SEQ_CONTROL *ctrl) WARN_UNUSED_RESULT
Places a KS_TRAP sequence object on a board at some position in the pulse sequence
Definition: KSFoundation_common.c:1802
#define KS_RAISE(status)
Definition: KSFoundation.h:190
typedef struct used as argument to ks_pg_*** functions to control where and when to place a sequence ...
Definition: KSFoundation.h:461
KS_TRAP postgrad
Definition: KSFoundation.h:1464
int ssi_time
Definition: KSFoundation.h:1226
STATUS ks_eval_seqctrl_setminduration(KS_SEQ_CONTROL *seqctrl, int mindur)
Sets the minimum duration and duration fields of a KS_SEQ_CONTROL struct based on some minimum time (...
Definition: KSFoundation_host.c:4921
KS_TRAP spoiler
Definition: ksepi_implementation.e:94
STATUS ksepi_diffusion_pg(KSEPI_SEQUENCE *epi, int TE)
Diffusion part of the ksepi_pg() function, placing diffusion gradients and the refocusing RF pulse in...
Definition: ksepi_implementation_diffusion.e:458
int time2center
Definition: KSFoundation.h:1944
KS_TRAP readphaser
Definition: KSFoundation.h:1934
int ksepi_echotime_shifting_sumdelay
Definition: ksepi_implementation.e:320
int psd_grd_wait
int ksepi_echogap
Definition: ksepi_implementation.e:224
#define KS_INIT_SEQLOC
Definition: KSFoundation.h:287
int duration
Definition: KSFoundation.h:673
int ksepi_slicecheck
Definition: ksepi_implementation.e:197
int psd_rf_wait
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
KS_WAIT pre_delay
Definition: ksepi_implementation.e:98
int ramptime
Definition: KSFoundation.h:671
int duration
Definition: KSFoundation.h:747
KS_WAIT post_delay
Definition: ksepi_implementation.e:99
#define KS_RFSSP_PRETIME
Definition: KSFoundation.h:217

◆ ksepi_scan_irslice()

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

Wrapper function to ksinv_scan_irslice() with ksepi_inv (global in this file) as argument

The inversion sequence's play function

Parameters
[in]slice_posPosition of the slice to be played out (one element in the global ks_scan_info[] array)
[in]dynamicPointer to KS_DYNAMIC_STATE struct, which has elements being automatically updated by the scan looping functions
Returns
KS_CORESLICETIME Time taken in [us] to play out one inversion slice (.duration) and time to center of inversion pulse (.referencetimepoint)
2942  {
2943 
2944  return ksinv_scan_irslice(&ksepi_inv, slice_pos, dynamic);
2945 
2946 } /* ksepi_scan_irslice() */
KSINV_MODULE ksepi_inv
Definition: ksepi_implementation.e:306
KS_CORESLICETIME ksinv_scan_irslice(KSINV_MODULE *seq, const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Plays out one inversion slice of the standard inversion module
Definition: ksinversion.cc:891

◆ ksepi_scan_coreslice()

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

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

The main EPI sequence's play function

This function updates the waveforms, and plays out, the ksepi sequence module. The low-level function call startseq(), which actually starts the realtime sequence playout is called from within ks_scan_playsequence(), which in addition also returns the time to play out that sequence module (see time += ...).

ks_scan_epi_loadecho() is called for data acquisition for each EPI readout.

After this, ksepi_scan_attach_metadata() adds additional data for each acqusition window for use in the recon_ksepi2.m Matlab script for sorting and reconstruction. To distinguish between the main and FLEET sequences, the sequence_group is here set to KSEPI_DATAGROUP_MAIN.

After each call to ks_scan_playsequence(), ks_plot_slicetime() is called to add slice-timing information for later HTML plotting of the sequence. As scanning is performed in real-time and may fail if interrupted, ks_plot_slicetime() will return quietly if it detects both IPG (TGT) and PSD_HW (on the MR scanner).

Common for all coreslice functions for any psd is the return of a KS_CORESLICETIME struct, which contains the time take to play out one slice (.duration) and the time from the start of the coreslice to the (.referencetimepoint) used to define the excitation location of the coreslice. Here this is simply ksepi.seqctrl.momentstart as there are no other embedded sequence modules played out inside this function. If any sequence module is added inside this function before/after ks_scan_playsequence(&ksepi.seqctrl), the KS_CORESLICETIME struct needs be updated accordingly.

Parameters
[in]slice_posPosition of the slice to be played out (one element in the global ks_scan_info[] array)
dynamicPointer to KS_DYNAMIC_STATE struct, which has elements being automatically updated by the scan looping functions
Return values
coreslicetimeKS_CORESLICETIME containing the time taken in [us] to play out one slice and the moment start of the slice
2982  {
2983  int echo;
2984  float tloc = 0.0;
2985  int i;
2987  SCAN_INFO slice_pos_updated;
2988 
2989  /* coord to first line of EPI train, same for all echoes */
2990  const KS_PHASEENCODING_COORD starting_coord = dynamic->shot_coords.entries == NULL ?
2991  fake_coord : dynamic->shot_coords.entries[0];
2992 
2993  /* Turn off blips during dummies */
2994  const ks_enum_epiblipsign blipsign = (starting_coord.ky < 0) ? KS_EPI_NOBLIPS : (ks_enum_epiblipsign) ksepi_blipsign;
2995 
2996  if (slice_pos != NULL) {
2997  /* uncomment to make transformations in the logical read-phase-slice coordinate system, using your own
2998  logic (e.g. radial or propeller applications), here just rotating by 30 degrees in-plane
2999  float rotz = 30.0;
3000  ks_mat4_setgeometry(dynamic->Mlogical, 0, 0, 0, 0, 0, rotz);
3001  Mphysical is useful for prospective motion correction implementations as it operates in X-Y-Z coords
3002  but should be left as the identity matrix otherwise
3003  */
3004  ks_scan_update_slice_location(&slice_pos_updated, *slice_pos, dynamic->Mphysical, dynamic->Mlogical);
3005  tloc = slice_pos_updated.optloc;
3006 
3007  /* modify sequence for next playout */
3008  ksepi_scan_seqstate(slice_pos_updated, starting_coord, blipsign);
3009  } else {
3010  /* false slice, shut off RF */
3012  }
3013 
3014  /* Scale diffusion gradients */
3015  for (i=0; i<3; ++i) {
3016  ks_scan_trap_ampscale(&ksepi.diffgrads[i], INSTRALL, dynamic->diff_amp[i]);
3017  }
3018 
3019  int dabslice = dynamic->sltimeinpass;
3020  if (ksepi.epitrain.zphaser.res > 1) {
3021  if (dynamic->slloc_offset) {
3022  dabslice = dynamic->slloc_offset - starting_coord.kz;
3023  } else {
3024  dabslice = starting_coord.kz;
3025  }
3026  }
3027 
3028  dynamic->force_acq = TRUE; /* always acquire data, also during dummies when the blips are off (for Nyquist ghost correction in recon_ksepi2.m) */
3029  for (echo = 0; echo < opnecho; echo++) {
3030  ks_scan_epi_loadecho(&ksepi.epitrain, echo, echo, dabslice, starting_coord, blipsign, dynamic);
3031  }
3032  if (ksepi_reflines > 0) {
3033  /* store phase reference lines as opnecho:th echo */
3034  /* ky of -2 will result in a view of -1 */
3035  /* See ksepi2_reconrules.txt for sorting info regarding shot and kyview */
3036  const KS_PHASEENCODING_COORD dynref_coord = {KS_NOTSET-1, KS_NOTSET};
3037  ks_scan_epi_loadecho(&ksepi.dynreftrain, 0, opnecho, dabslice, dynref_coord, KS_EPI_NOBLIPS, dynamic);
3038  }
3039 
3040  /* attach metadata to all EPI readout windows */
3042  ksepi_scan_attach_metadata(&ksepi.epitrain, &ksepi.dynreftrain, dynamic, sequence_group);
3043 
3045 
3047  slicetime.duration += ks_scan_playsequence(&ksepi.seqctrl);
3048 
3049  ks_plot_slicetime(&ksepi.seqctrl, 1, &tloc, opslthick, slice_pos == NULL ? KS_PLOT_NO_EXCITATION : KS_PLOT_STANDARD);
3050 
3051  return slicetime;
3052 
3053 } /* ksepi_scan_coreslice() */
#define KS_INIT_PHASEENCODING_COORD
Definition: KSFoundation.h:306
STATUS ksepi_scan_seqstate(SCAN_INFO slice_pos, KS_PHASEENCODING_COORD starting_coord, ks_enum_epiblipsign blipsign)
Sets the current state of all ksepi sequence objects at every ksepi playout in scan
Definition: ksepi_implementation.e:2633
int res
Definition: KSFoundation.h:1721
void ks_scan_trap_ampscale(KS_TRAP *trap, int instanceno, float ampscale)
Updates the amplitude of one or all instances of a KS_TRAP sequence object
Definition: KSFoundation_tgt.c:306
#define KS_NOTSET
Definition: KSFoundation.h:115
Definition: ksepi_implementation.e:125
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
KS_EPI dynreftrain
Definition: ksepi_implementation.e:93
int momentstart
Definition: KSFoundation.h:1228
Duration and RF center (for excitation or inversion as applicable) of a coreslice/irslice function (h...
Definition: ksscan.h:72
KS_PHASER zphaser
Definition: KSFoundation.h:1938
s16 ky
Definition: KSFoundation.h:1750
KS_EPI epitrain
Definition: ksepi_implementation.e:92
int duration
Definition: ksscan.h:73
Struct holding a 3D k-space phase encoding location (ky,kz)
Definition: KSFoundation.h:1749
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:91
Definition: KSFoundation.h:2329
int ks_scan_playsequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1644
void ks_scan_epi_loadecho(KS_EPI *epi, int echo, int storeecho, int slice, KS_PHASEENCODING_COORD starting_coord, ks_enum_epiblipsign blipsign, KS_DYNAMIC_STATE *dynamic)
Loads the data storage information to hardware for the acquisition windows in a KS_EPI sequence objec...
Definition: KSFoundation_tgt.c:1419
Definition: KSFoundation.h:404
int epi_readout_mode
Definition: KSFoundation.h:1939
Definition: KSFoundation.h:403
int referencetimepoint
Definition: ksscan.h:74
#define KS_INIT_CORESLICETIME
Definition: ksscan.h:77
int ksepi_blipsign
Definition: ksepi_implementation.e:233
void ksepi_scan_rf_off()
Sets all RF pulse amplitudes to zero
Definition: ksepi_implementation.e:2755
ks_enum_epiblipsign
Definition: KSFoundation.h:2330
void ksepi_scan_attach_metadata(KSEPI_SEQUENCE *seq, const KS_DYNAMIC_STATE *dynamic, uint8_t sequence_group)
Definition: ksepi_implementation.e:125
s16 kz
Definition: KSFoundation.h:1751
int ksepi_reflines
Definition: ksepi_implementation.e:261
void ks_scan_update_slice_location(SCAN_INFO *new_loc, const SCAN_INFO orig_loc, const KS_MAT4x4 M_physical, const KS_MAT4x4 M_logical)
Updates a SCAN_INFO struct using physical and logical 4x4 transformation matrices
Definition: KSFoundation_common.c:4015
void ks_plot_slicetime(const KS_SEQ_CONTROL *ctrl, int nslices, float *slicepos_mm, float slthick_mm, KS_PLOT_EXCITATION_MODE exctype)
ADDTITLEHERE
Definition: KSFoundation_common.c:4276
Definition: KSFoundation.h:2330
float opslthick
KS_TRAP diffgrads[3]
Definition: ksepi_implementation.e:97

◆ ksepi_scan_coreslicegroup()

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

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

The main EPI sequence + potential other modules' play function

With the use of generic scan loops (ksscan.cc:ksscan_scanloop()) performing the actual scan in ksepi_scan_scanloop(), using

one needs to create the psd-specific function in this file to play out one slice of one or more sequence modules This is that function, which must take (const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic) as the two input arguments, and return a KS_CORESLICETIME struct. This to match the various ksscan_****loop() functions in ksscan.cc, used to run the scan.

Unlike ksepi_scan_coreslice(), which only plays the main sequence (ksepi), this function also plays other sequence modules. For now, this is only the kssat sequence module, which is played out before the main sequence, if active.

Parameters
[in]slice_posPointer to the SCAN_INFO struct corresponding to the current slice to be played out
dynamicPointer to KS_DYNAMIC_STATE struct, which has elements being automatically updated by the scan looping functions
Returns
coreslicetime KS_CORESLICETIME containing the time taken in [us] to play out one slice and the moment start of the slice
3081  {
3082  KS_CORESLICETIME coreslicetime = KS_INIT_CORESLICETIME;
3083  int premainseq_duration = 0;
3084 
3085  /* Sat */
3086  premainseq_duration += kssat_scan(slice_pos, dynamic, &kssat);
3087 
3088  /* Main */
3089  coreslicetime = ksepi_scan_coreslice(slice_pos, dynamic);
3090 
3091  coreslicetime.duration += premainseq_duration;
3092  coreslicetime.referencetimepoint += premainseq_duration;
3093 
3094  return coreslicetime;
3095 
3096 } /* ksepi_scan_coreslicegroup() */
int kssat_scan(const SCAN_INFO *slice_info, KS_DYNAMIC_STATE *dynamic, KSSAT_MODULE *sat)
Change the dynamic state for a saturation module
Definition: kssat.e:239
KS_CORESLICETIME ksepi_scan_coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Plays out one slice for the ksepi sequence module in real time during scanning
Definition: ksepi_implementation.e:2982
Duration and RF center (for excitation or inversion as applicable) of a coreslice/irslice function (h...
Definition: ksscan.h:72
int duration
Definition: ksscan.h:73
KSSAT_MODULE kssat
Definition: kssat.e:112
int referencetimepoint
Definition: ksscan.h:74
#define KS_INIT_CORESLICETIME
Definition: ksscan.h:77

◆ ksepi_scan_fleet_coreslice()

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

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

The FLEET EPI sequence's play function

This function updates the waveforms, and plays out, the ksepi_fleetseq sequence module. It is quite similar to ksepi_scan_coreslice(), but with the FLEET sequence module instead of the main EPI sequence. In this function, sequence_group = KSEPI_DATAGROUP_FLEET, while it is KSEPI_DATAGROUP_MAIN in ksepi_scan_coreslice(), to let recon detect which readout windows are FLEET vs MAIN.

Parameters
[in]slice_posPosition of the slice to be played out (one element in the global ks_scan_info[] array)
dynamicPointer to KS_DYNAMIC_STATE struct, which has elements being automatically updated by the scan looping functions
Returns
coreslicetime KS_CORESLICETIME containing the time taken in [us] to play out one slice and the moment start of the slice
3114  {
3115  float tloc = 0.0;
3118 
3119  if (ksepi_fleetseq.seqctrl.duration == 0) {
3120  return slicetime;
3121  }
3122 
3123  /* coord to first line of EPI train */
3124  const KS_PHASEENCODING_COORD starting_coord = dynamic->shot_coords.entries == NULL ?
3125  fake_coord : dynamic->shot_coords.entries[0];
3126 
3127  /* Turn off blips during dummies */
3128  const ks_enum_epiblipsign blipsign = (starting_coord.ky < 0) ? KS_EPI_NOBLIPS : (ks_enum_epiblipsign) ksepi_blipsign;
3129 
3130  ksepi_fleet_scan_seqstate(slice_pos, starting_coord, blipsign);
3131 
3132  int dabslice = dynamic->sltimeinpass;
3133  if (ksepi_fleetseq.epitrain.zphaser.res > 1) {
3134  if (dynamic->slloc_offset) {
3135  dabslice = dynamic->slloc_offset - starting_coord.kz;
3136  } else {
3137  dabslice = starting_coord.kz;
3138  }
3139  }
3140 
3141  dynamic->force_acq = TRUE; /* always acquire the FLEET data, also during dummies when the blips are off (for Nyquist ghost correction in recon_ksepi2.m) */
3142  ks_scan_epi_loadecho(&ksepi_fleetseq.epitrain, 0, 0, dabslice, starting_coord, blipsign, dynamic);
3143 
3144  /* attach metadata to all EPI readout windows */
3146  ksepi_scan_attach_metadata(&ksepi_fleetseq.epitrain, NULL, dynamic, sequence_group);
3147 
3150 
3151  tloc = (slice_pos != NULL) ? slice_pos->optloc : 0.0;
3153  slice_pos == NULL ? KS_PLOT_NO_EXCITATION : KS_PLOT_STANDARD);
3154 
3155  return slicetime;
3156 
3157 } /* ksepi_scan_fleet_coreslice() */
#define KS_INIT_PHASEENCODING_COORD
Definition: KSFoundation.h:306
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:114
int res
Definition: KSFoundation.h:1721
int momentstart
Definition: KSFoundation.h:1228
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:302
Duration and RF center (for excitation or inversion as applicable) of a coreslice/irslice function (h...
Definition: ksscan.h:72
KS_PHASER zphaser
Definition: KSFoundation.h:1938
int duration
Definition: KSFoundation.h:1227
s16 ky
Definition: KSFoundation.h:1750
int duration
Definition: ksscan.h:73
Struct holding a 3D k-space phase encoding location (ky,kz)
Definition: KSFoundation.h:1749
Definition: ksepi_implementation.e:125
Definition: KSFoundation.h:2329
int ks_scan_playsequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1644
void ks_scan_epi_loadecho(KS_EPI *epi, int echo, int storeecho, int slice, KS_PHASEENCODING_COORD starting_coord, ks_enum_epiblipsign blipsign, KS_DYNAMIC_STATE *dynamic)
Loads the data storage information to hardware for the acquisition windows in a KS_EPI sequence objec...
Definition: KSFoundation_tgt.c:1419
Definition: KSFoundation.h:404
STATUS ksepi_fleet_scan_seqstate(const SCAN_INFO *slice_pos, KS_PHASEENCODING_COORD starting_coord, ks_enum_epiblipsign blipsign)
Sets the current state of all FLEET sequence objects at every FLEET sequence playout in scan...
Definition: ksepi_implementation.e:2701
int epi_readout_mode
Definition: KSFoundation.h:1939
Definition: KSFoundation.h:403
int referencetimepoint
Definition: ksscan.h:74
#define KS_INIT_CORESLICETIME
Definition: ksscan.h:77
int ksepi_blipsign
Definition: ksepi_implementation.e:233
ks_enum_epiblipsign
Definition: KSFoundation.h:2330
void ksepi_scan_attach_metadata(KSEPI_SEQUENCE *seq, const KS_DYNAMIC_STATE *dynamic, uint8_t sequence_group)
s16 kz
Definition: KSFoundation.h:1751
void ks_plot_slicetime(const KS_SEQ_CONTROL *ctrl, int nslices, float *slicepos_mm, float slthick_mm, KS_PLOT_EXCITATION_MODE exctype)
ADDTITLEHERE
Definition: KSFoundation_common.c:4276
Definition: KSFoundation.h:2330
KS_SELRF selrfexc
Definition: ksepi_implementation.e:117
Definition: ksepi_implementation.e:125
float slthick
Definition: KSFoundation.h:1456
KS_EPI epitrain
Definition: ksepi_implementation.e:115

◆ ksepi_scan_attach_metadata() [1/2]

void ksepi_scan_attach_metadata ( KSEPI_SEQUENCE seq,
const KS_DYNAMIC_STATE *  dynamic,
uint8_t  sequence_group 
)

◆ ksepi_dump_metadata()

void ksepi_dump_metadata ( KSEPI_METADATA metadata,
const KS_DYNAMIC_STATE *  dynamic 
)

Write out a textfile of the metadata created in ksepi_scan_attach_metadata() (WTools only)

This debugging function can be used to find errors in the datastore tags of this sequence, created in ksepi_scan_attach_metadata(). Alternatively, this can be done graphically in Matlab (recon_ksepi2.m -> recon_ksepi2_splitdata.m)

Parameters
metadataPointer to KSEPI_METADATA
dynamicPointer to KS_DYNAMIC_STATE
Returns
void
2775  {
2776  (void) metadata;
2777  (void) dynamic;
2778 
2779 #ifdef SIM
2780  /* in simulation (WTools) only */
2781 
2782  if (dynamic->slloc != 0) { /* only show for one slice */
2783  return;
2784  }
2785 
2786  FILE *fp;
2787  fp = fopen("ksepi_metadump.txt","a");
2788 
2789  char str[200] = "00000";
2790  static char laststr[200] = "1234";
2791 
2792  float bscale = \
2793  dynamic->diff_amp[XGRAD] * dynamic->diff_amp[XGRAD] + \
2794  dynamic->diff_amp[YGRAD] * dynamic->diff_amp[YGRAD] + \
2795  dynamic->diff_amp[ZGRAD] * dynamic->diff_amp[ZGRAD];
2796 
2797  char tmpstr[40];
2798 
2799  switch (metadata->sequence_group) {
2800  case KSEPI_SEQINDEX_MAIN:
2801  strcpy(tmpstr, "MAIN ");
2802  break;
2803  case KSEPI_SEQINDEX_FLEET:
2804  strcpy(tmpstr, "FLEET ");
2805  break;
2807  strcpy(tmpstr, "MAIN_SPLIT ");
2808  break;
2810  strcpy(tmpstr, "FLEET_SPLIT");
2811  break;
2812  }
2813  sprintf(str, "%s ", tmpstr);
2814 
2815  switch (metadata->seqpart) {
2817  strcpy(tmpstr, "EPITRAIN ");
2818  break;
2820  strcpy(tmpstr, "DYNREFTRAIN");
2821  break;
2822  case KSEPI_SEQPART_FIDNAV:
2823  strcpy(tmpstr, "FIDNAV ");
2824  break;
2825  }
2826  sprintf(str, "%s%s ", str, tmpstr);
2827 
2828  sprintf(str, "%sv%d ", str, metadata->vol_rep);
2829  sprintf(str, "%ssh%+d ", str, metadata->shot);
2830  sprintf(str, "%sish%+d ", str, metadata->inner_shot);
2831  sprintf(str, "%sa%d ", str, metadata->average);
2832  sprintf(str, "%srp%+d ", str, metadata->readpolarity);
2833  sprintf(str, "%sDx%+.1f ", str, dynamic->diff_amp[XGRAD]);
2834  sprintf(str, "%sDy%+.1f ", str, dynamic->diff_amp[YGRAD]);
2835  sprintf(str, "%sDz%+.1f ", str, dynamic->diff_amp[ZGRAD]);
2836  sprintf(str, "%sb%d ", str, (int) (bscale * opbval + 0.5));
2837  sprintf(str, "%s\n", str);
2838 
2839  if (1 || strcmp(str, laststr)) {
2840  fprintf(fp, "%s", str);
2841  strcpy(laststr, str);
2842  }
2843 
2844  fclose(fp);
2845 
2846 #endif
2847 
2848 } /* ksepi_dump_metadata() */
int8_t average
Definition: ksepi_implementation.e:162
Definition: ksepi_implementation.e:126
Definition: ksepi_implementation.e:125
int16_t vol_rep
Definition: ksepi_implementation.e:166
int8_t readpolarity
Definition: ksepi_implementation.e:171
Definition: ksepi_implementation.e:126
uint8_t seqpart
Definition: ksepi_implementation.e:172
Definition: ksepi_implementation.e:125
Definition: ksepi_implementation.e:126
int8_t inner_shot
Definition: ksepi_implementation.e:170
int16_t shot
Definition: ksepi_implementation.e:165
uint8_t sequence_group
Definition: ksepi_implementation.e:161
Definition: ksepi_implementation.e:125
Definition: ksepi_implementation.e:125

◆ ksepi_set_loop_control_design()

STATUS ksepi_set_loop_control_design ( KSSCAN_LOOP_CONTROL_DESIGN loop_design,
const KS_EPI epitrain 
)

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

This function creates a KSSCAN_LOOP_CONTROL_DESIGN struct, with fields .dda: Number of dummy scans .naverages: Number of averages .nvols: Number of volumes .phaseenc_design: KS_PHASEENCODING_DESIGN (containing coordinates and other phase encoding info) .slicetiming_design: KS_SLICETIMING_DESIGN (containing slice timing info)

This function is called from ksepi_eval_loops() to produce a KSSCAN_LOOP_CONTROL_DESIGN, which is then used in part to create a KSSCAN_LOOP_CONTROL struct used in scan

Note that all design structs are short-lived and are set up as a receipe for other structures to be used in pulsegen and scan

Parameters
[out]loop_designKSSCAN_LOOP_CONTROL_DESIGN to be created
[in]epitrainKS_EPI struct with .blipphaser and .zphaser fields steering the set of k-space coordinates to reach
Return values
STATUSSUCCESS or FAILURE
1593  {
1594 
1595  if (optr >= 1s) {
1596  ksepi_dda = 1;
1597  } else if (optr > 350ms) {
1598  ksepi_dda = 2;
1599  } else {
1600  ksepi_dda = 4;
1601  }
1602 
1603  loop_design->dda = IMax(2, 1, ksepi_dda); /* safety net to ensure at least one dummy (for Nyquist ghost correction in recon_ksepi2.m) */
1604  /* NEX usage for diffusion (opdiffuse): ksdiffusion.cc:ksdiff_schemeloop() uses
1605  - ksepi_loopctrl.naverages (next line) for b0 NEX
1606  - ksepi_diffctrl.multib_nex[bvalue_idx] as NEX for each b-value */
1607  loop_design->naverages = opdiffuse ? opdifnext2 /* NEX for b0s */ : ceil(opnex);
1608  loop_design->nvols = opfphases;
1609 
1610  /* Generate the k-space coordinate list */
1611  STATUS s = ks_generate_3d_coords_epi(&kacq,
1612  epitrain,
1614  epitrain->R_ky,
1615  0 /* caipi */);
1616  KS_RAISE(s);
1617 
1618  /* Phase encoding */
1619  loop_design->phaseenc_design.encodes_per_shot = opnecho;
1620  loop_design->phaseenc_design.center_encode = 0;
1621  loop_design->phaseenc_design.kacq = kacq;
1622  loop_design->phaseenc_design.encode_shot_assignment_order = Z_Y; /* shot order. image ghosting occurs if Y_Z, important for SWI // HR */
1623  loop_design->phaseenc_design.repeat.num_repeats = opnecho;
1625  ks_create_suffixed_description(loop_design->phaseenc_design.description, ksepi.seqctrl.description, " - phase encoding plan");
1626 
1627 
1629 
1630  return SUCCESS;
1631 
1632 } /* ksepi_set_loop_control_design() */
int encodes_per_shot
Definition: ksscan.h:140
STATUS ks_generate_3d_coords_epi(KS_KSPACE_ACQ *kacq, const KS_EPI *epitrain, const ks_enum_epiblipsign blipsign, const int Ry, const int caipi_delta) WARN_UNUSED_RESULT
ADDTITLEHERE
Definition: KSFoundation_host.c:10433
KS_KSPACE_ACQ kacq
Definition: ksscan.h:138
int R_ky
Definition: KSFoundation.h:1940
int naverages
Definition: ksscan.h:204
KS_VIEW_SORT_ORDER encode_shot_assignment_order
Definition: ksscan.h:143
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
KS_PHASEENCODING_PLAN_DESIGN phaseenc_design
Definition: ksscan.h:207
KS_DESCRIPTION description
Definition: ksscan.h:137
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:91
int dda
Definition: ksscan.h:202
void ks_create_suffixed_description(char *const out, const char *const prefix, const char *suffix,...) __attribute__((format(printf
KS_PHASEENCODING_REPEAT_DESIGN repeat
Definition: ksscan.h:145
int nvols
Definition: ksscan.h:203
KS_SLICETIMING_DESIGN slicetiming_design
Definition: ksscan.h:209
KS_REPEAT_MODE mode
Definition: KSFoundation.h:2258
#define KS_RAISE(status)
Definition: KSFoundation.h:190
int ksepi_dda
Definition: ksepi_implementation.e:273
int ksepi_blipsign
Definition: ksepi_implementation.e:233
int center_encode
Definition: ksscan.h:141
ks_enum_epiblipsign
Definition: KSFoundation.h:2330
Definition: KSFoundation.h:2244
void ksepi_set_slicetiming_design(KS_SLICETIMING_DESIGN *slicetiming_design)
Set up the number of slices, TR range, and min num acquisitions in KS_SLICETIMING_DESIGN
Definition: ksepi_implementation.e:1546
KS_DESCRIPTION description
Definition: KSFoundation.h:1234
KS_KSPACE_ACQ kacq
Definition: ksepi_implementation.e:355
int num_repeats
Definition: KSFoundation.h:2259
Definition: KSFoundation.h:2119

◆ ksepi_scan_seqstate()

STATUS ksepi_scan_seqstate ( SCAN_INFO  slice_pos,
KS_PHASEENCODING_COORD  starting_coord,
ks_enum_epiblipsign  blipsign 
)

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

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 for a given sequence playout in ksepi_scan_coreslice() during scan.

Note that starting_coord is the first line in the EPI train.

Parameters
[in]slice_posPosition of the slice to be played out (one element in the ks_scan_info[] array)
[in]starting_coordKS_PHASEENCODING_COORD holding the .ky and .kz coordinates of the first line in the EPI train
[in]blipsignSign of the EPI blips: [-1]:Negative (k-space top-down) [1]:Positive (k-space bottom-up) [0]:No blips
Return values
STATUSSUCCESS or FAILURE
2633  {
2634  int echo;
2635  float exc_rfphase;
2636 
2637  /* RF frequency & phase */
2638  if (ksepi_rfspoiling) {
2641  } else {
2642  exc_rfphase = 0;
2643  }
2644 
2645  ks_scan_rotate(slice_pos);
2646 
2647  ks_scan_rf_on(&ksepi.selrfexc.rf, INSTRALL);
2648  ks_scan_rf_on(&ksepi.selrfref.rf, INSTRALL);
2649 
2650  ks_scan_selrf_setfreqphase(&ksepi.selrfexc, 0, slice_pos, exc_rfphase);
2651  ks_scan_selrf_setfreqphase(&ksepi.selrfref, INSTRALL, slice_pos, exc_rfphase+90);
2652 
2653  /* Echo time shifting */
2655  int pre_delay = ksepi.pre_delay.pg_duration;
2656  int post_delay = ksepi.post_delay.pg_duration;
2657  int kyshot = starting_coord.ky % ksepi.epitrain.blipphaser.R;
2659  float delta_t = (float) epiesp / (float) ksepi.epitrain.blipphaser.R;
2660 
2661  if (kyshot >= 0) {
2662  if (blipsign == KS_EPI_POSBLIPS) {
2663  pre_delay = RUP_GRD((int) (delta_t * (ksepi.epitrain.blipphaser.R-1-kyshot)));
2664  } else if (blipsign == KS_EPI_NEGBLIPS) {
2665  pre_delay = RUP_GRD((int) (delta_t * kyshot));
2666  }
2667  }
2668  ks_scan_wait(&ksepi.pre_delay, pre_delay);
2669  post_delay = ksepi_echotime_shifting_sumdelay - pre_delay;
2670  ks_scan_wait(&ksepi.post_delay, post_delay);
2671  } /* echotime shifting */
2672 
2673  /* EPI echoes (i.e. EPI trains) */
2674  for (echo = 0; echo < opnecho; echo++) {
2675  ks_scan_epi_shotcontrol(&ksepi.epitrain, echo, slice_pos, starting_coord, blipsign, exc_rfphase);
2676  } /* opnecho */
2677 
2678  KS_PHASEENCODING_COORD fake_coord = {KS_NOTSET, KS_NOTSET};
2679  ks_scan_epi_shotcontrol(&ksepi.dynreftrain, 0, slice_pos, fake_coord, KS_EPI_NOBLIPS, exc_rfphase);
2680 
2681  return SUCCESS;
2682 
2683 } /* 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:566
void ks_scan_epi_shotcontrol(KS_EPI *epi, int echo, SCAN_INFO sliceinfo, KS_PHASEENCODING_COORD starting_coord, ks_enum_epiblipsign blipsign, float rcvphase)
Changes the gradient state of a KS_EPI object for the given slice information
Definition: KSFoundation_tgt.c:1405
float ks_scan_rf_phase_spoiling(int counter)
Returns spoiling phase for a given RF counter
Definition: KSFoundation_common.c:4827
int R
Definition: KSFoundation.h:1723
int ksepi_rfspoiling
Definition: ksepi_implementation.e:199
KS_SELRF selrfexc
Definition: ksepi_implementation.e:95
#define KS_NOTSET
Definition: KSFoundation.h:115
int ksepi_echotime_shifting
Definition: ksepi_implementation.e:234
KS_PHASER blipphaser
Definition: KSFoundation.h:1937
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
KS_EPI dynreftrain
Definition: ksepi_implementation.e:93
s16 ky
Definition: KSFoundation.h:1750
KS_TRAP grad
Definition: KSFoundation.h:1561
KS_EPI epitrain
Definition: ksepi_implementation.e:92
Struct holding a 3D k-space phase encoding location (ky,kz)
Definition: KSFoundation.h:1749
void ks_scan_selrf_setfreqphase(KS_SELRF *selrf, int instanceno, SCAN_INFO sliceinfo, float rfphase)
Updates the frequency and phase of one or all instances of a slice selective RF pulse (KS_SELRF)...
Definition: KSFoundation_tgt.c:683
KS_RF rf
Definition: KSFoundation.h:1454
KS_SELRF selrfref
Definition: ksepi_implementation.e:96
KS_READTRAP read
Definition: KSFoundation.h:1932
Definition: KSFoundation.h:2330
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:161
int pg_duration
Definition: KSFoundation.h:545
void ks_scan_rotate(SCAN_INFO slice_pos)
Performs a rotation of the logical system on hardware (WARP)
Definition: KSFoundation_tgt.c:1179
int ksepi_echotime_shifting_sumdelay
Definition: ksepi_implementation.e:320
int read_spacing
Definition: KSFoundation.h:1942
int duration
Definition: KSFoundation.h:673
Definition: KSFoundation.h:2330
int rfspoiling_phase_counter
Definition: ksepi_implementation.e:3221
KS_WAIT pre_delay
Definition: ksepi_implementation.e:98
Definition: KSFoundation.h:2330
KS_WAIT post_delay
Definition: ksepi_implementation.e:99

◆ ksepi_scan_scanloop()

s64 ksepi_scan_scanloop ( )

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

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

This function first completes the FLEET scan, for 2D imaging with parallel imaging, where the FLEET scan is used in recon for motion robust GRAPPA calibration.

If inversion is used, the function calls ksinv_scan_scanloop(), where ksepi_inv_loopctrl is used to control the the scan looping. For non-inversion scans, depending on if diffusion is used, either ksdiff_schemeloop() or ksscan_scanloop() is called, where ksepi_loopctrl is used to control the scan looping in both cases. ksscan_scanloop() and ksdiff_schemeloop() differ only on the outer volumne loop, but share the same inner looping from ksscan_acqloop(). While ksscan_scanloop() goes through volume indices like fMRI, ksdiff_schemeloop() goes through diffusion directions and b-values as different volumes.

Returns
scantime Total scan time in [us]
3180  {
3181  s64 time = 0;
3182 
3183 #ifdef SIM
3184  /* empty local file in simulation (see ksepi_dump_metadata()) */
3185  FILE *fp = fopen("ksepi_metadump.txt","w"); fclose(fp);
3186 #endif
3187 
3188  if (ksepi_fleet) {
3190  }
3191 
3192  KS_DYNAMIC_STATE dynamic = KS_INIT_DYNAMIC_STATE;
3193 
3194  if (!ANYINVERSION) {
3195  if (opdiffuse) {
3197  } else {
3199  }
3200  } else {
3202  }
3203 
3204  return time; /* in [us] */
3205 
3206 } /* ksepi_scan_scanloop() */
KSDIFF_CONTROL ksepi_diffctrl
Definition: ksepi_implementation.e:299
s64 ksinv_scan_scanloop(KSINV_LOOP_CONTROL *inv_loopctrl, KS_DYNAMIC_STATE *dynamic, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), KS_CORESLICETIME irslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
Plays the entire scan for an inversion loop control
Definition: ksinversion.cc:1224
KSINV_LOOP_CONTROL ksepi_inv_loopctrl
Definition: ksepi_implementation.e:307
s64 ksdiff_schemeloop(const KSDIFF_CONTROL *diff_control, const KSSCAN_LOOP_CONTROL *orig_loop_control, KS_DYNAMIC_STATE *dynamic, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
Executes all loops for a diffusion scheme according to the provided loop control
Definition: ksdiffusion.cc:428
KS_CORESLICETIME ksepi_scan_irslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Wrapper function to ksinv_scan_irslice() with ksepi_inv (global in this file) as argument
Definition: ksepi_implementation.e:2942
#define KS_INIT_DYNAMIC_STATE
Definition: KSFoundation.h:1829
KSSCAN_LOOP_CONTROL ksepi_loopctrl
Definition: ksepi_implementation.e:298
KSSCAN_LOOP_CONTROL ksepi_fleet_loopctrl
Definition: ksepi_implementation.e:303
s64 ksscan_scanloop(const KSSCAN_LOOP_CONTROL *orig_loop_control, KS_DYNAMIC_STATE *dynamic, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
Executes all loops according to the provided loop control
Definition: ksscan.cc:564
KS_CORESLICETIME ksepi_scan_coreslicegroup(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Function to run for scan to execute one slice of the ksepi sequence module with optional sat module...
Definition: ksepi_implementation.e:3081
#define ANYINVERSION
Definition: KSFoundation.h:346
int ksepi_fleet
Definition: ksepi_implementation.e:250
KS_CORESLICETIME ksepi_scan_fleet_coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Plays out one slice for the ksepi_fleetseq sequence module in real time during scanning
Definition: ksepi_implementation.e:3114

◆ ksepi_get_loop_ctrl()

const KSSCAN_LOOP_CONTROL * ksepi_get_loop_ctrl ( )

Function to automatically switch between inverision and standard loop control

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

Return values
STATUSSUCCESS or FAILURE
2300  {
2301  return ANYINVERSION ?
2303 
2304 } /* ksepi_get_loop_ctrl() */
KSINV_LOOP_CONTROL ksepi_inv_loopctrl
Definition: ksepi_implementation.e:307
KSSCAN_LOOP_CONTROL ksepi_loopctrl
Definition: ksepi_implementation.e:298
KSSCAN_LOOP_CONTROL loopctrl
Definition: ksinversion.h:110
#define ANYINVERSION
Definition: KSFoundation.h:346

◆ 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
400  {
401  int numopts = sizeof(sequence_iopts) / sizeof(int);
402 
403  psd_init_iopt_activity();
404  activate_iopt_list(numopts, sequence_iopts);
405  enable_iopt_list(numopts, sequence_iopts);
406 
407  /* Imaging option control functions (using PSD_IOPT_ZIP_512 as example):
408  - Make an option unchecked and not selectable: disable_ioption(PSD_IOPT_ZIP_512)
409  - Make an option checked and not selectable: set_required_disabled_option(PSD_IOPT_ZIP_512)
410  - Remove the imaging option: deactivate_ioption(PSD_IOPT_ZIP_512)
411  */
412 
413 
414  cvset(opptsize, 2, 4, 4, ""); /* EDR */
415  set_required_disabled_option(PSD_IOPT_EDR); /* always use EDR, don't change */
416 
417  /* Do not allow 3D multislab to be selected until supported by the PSD */
418  cvmax(opimode, PSD_3D);
419 
420  /* Button accept control */
421  cvmax(opflair, OPFLAIR_GROUP); /* allow T2-FLAIR */
422  cvmax(opepi, 1);
423  cvdef(opepi, 1);
424  cvmax(opmph, 1);
425  cvmax(opdiffuse, 1);
426 
427  /* Exlude different inversion types */
428  set_incompatible(PSD_IOPT_T2FLAIR, PSD_IOPT_T1FLAIR);
429  set_incompatible(PSD_IOPT_IR_PREP, PSD_IOPT_T1FLAIR);
430  set_incompatible(PSD_IOPT_T2FLAIR, PSD_IOPT_IR_PREP);
431 
432  if (KS_3D_SELECTED) {
433  deactivate_ioption(PSD_IOPT_IR_PREP);
434  }
435 
436  /* flow comp only for GE-EPI */
437  if (exist(oppseq) == PSD_SE) {
438  deactivate_ioption(PSD_IOPT_FLOW_COMP);
439  }
440 
441 
442  if (opdiffuse) {
443  deactivate_ioption(PSD_IOPT_SEQUENTIAL);
444  deactivate_ioption(PSD_IOPT_MPH);
445  deactivate_ioption(PSD_IOPT_IR_PREP);
446  }
447 
448 #ifdef SIM
449  opepi = !KS_3D_SELECTED;
450  setexist(opepi, PSD_ON);
451  opirmode = PSD_OFF; /* default interleaved slices */
452  setexist(opirmode, PSD_ON);
453 #endif
454 
455  /* GERequired.e:GEReq_cvinit() sets ks_qfact (acoustic reduction) when
456  ART (opsilent) has been selected. For medium/high ART, ks_qfact is set to 8/20.
457  However, for EPI, the geometric distortions becomes too severe so can no
458  reduce the slewrate for EPI as much (and hence the amount of acoustic reduction).
459 
460  Also the SPSP RF pulse uses a gradwave that cannot be derated.
461  If we use SPSP RF exc (opfat == FALSE), we set ks_qfact = 1.0.
462  With opfat ks_qfact will be set by GEReq_cvinit() and the sequence will run quieter
463  In all cases, the EPI readout gradients are controlled by ksepi_epiqfact */
464 
465  if (opsilent) {
466 
467  if (opfat == FALSE) {
468  /* SPectral-SPatial RF. Cannot derate excitation waveform */
469  ks_qfact = 1.0; /* for all gradients except the EPI readout */
471  }
472 
473  if (opsilentlevel == 1) {
474  /* moderate ART (small acoustic reduction) */
475  ksepi_epiqfact = 3.0;
476  } else {
477  /* high ART (moderate acoustic reduction) */
478  ksepi_epiqfact = 6.0; /* for the EPI readout */
479  }
480  } else {
481  ksepi_epiqfact = 1.0;
482  }
483 
484  pipure = PSD_PURE_COMPATIBLE_2; /* or maybe PSD_PURE_COMPATIBLE_1 ? */
485 
486  /* RF Drive mode (default to 'Quadrature') */
487  cvdef(opdrivemode, 2);
488  opdrivemode = _opdrivemode.defval;
489 
490  ks_plot_kstmp = TRUE; /* save plots to kstmp */
491 
492  /* default receive gain (LOW/HIGH for 3D/2D). No APS2 prescan with ksepi_recvgain_mode > 0 */
493  ksepi_recvgain_mode = (KS_3D_SELECTED) ? RG_CAL_MODE_LOW_FIXED : RG_CAL_MODE_HIGH_FIXED;
494 
495 } /* ksepi_init_imagingoptions() */
STATUS GEReq_init_gradspecs(LOG_GRAD *loggrd, PHYS_GRAD *phygrd, float srfact)
Initialize logical and physical gradient specifications
Definition: GERequired.e:435
int ksepi_recvgain_mode
Definition: ksepi_implementation.e:279
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
PHYS_GRAD phygrd
float ks_qfact
Definition: GERequired.e:271
int sequence_iopts[]
Definition: ksepi_implementation.e:376
LOG_GRAD loggrd
#define cvset(cv, min, max, def, desc)
Definition: KSFoundation.h:2380
float ksepi_epiqfact
Definition: ksepi_implementation.e:278
float ks_srfact
Definition: GERequired.e:270
int ks_plot_kstmp
Definition: GERequired.e:273

◆ 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
505  {
506  STATUS status;
507 
508  /* Slice oversampling for 3D to avoid aliasing */
509  if (KS_3D_SELECTED) {
510  pislblank = ksepi_kissoff_factor * exist(opslquant);
511  }
512 
513  /* Spin or Gradient Echo EPI */
514  if (exist(oppseq) == PSD_SE || exist(oppseq) == PSD_IR) {
515  acq_type = TYPSPIN; /* SE, FLAIR, or Diffusion EPI */
516  } else {
517  acq_type = TYPGRAD; /* GRE-EPI */
518  }
519 
520  /* force flow comp off for non-GE-EPI */
521  if (acq_type != TYPGRAD) {
522  cvoverride(opfcomp, FALSE, PSD_FIX_ON, PSD_EXIST_ON);
523  }
524 
525  /* rBW */
526  float bw_3Dlimit = (cfgcoiltype == PSD_XRMW_COIL) ? 83.33 : 125.0;
527  pidefrbw = (KS_3D_SELECTED) ? bw_3Dlimit : 250.0;
528  cvset(oprbw, 15.625, pidefrbw, pidefrbw, "");
529  pircbnub = (cfgcoiltype == PSD_XRMW_COIL) ? 4 : 5; /* number of variable bandwidth */
530  pircb2nub = 0; /* no second bandwidth option */
531  pircbval2 = 31.25;
532  pircbval3 = 62.50;
533  pircbval4 = (KS_3D_SELECTED) ? 83.33 : 125.0;
534  pircbval5 = pidefrbw;
535 
536  /* NEX - never show. Partial Fourier in ky is done with opte = MINTE, not with NEX < 1 */
537  cvdef(opnex, 1);
538  opnex = _opnex.defval;
539  cvmin(opnex, 1);
540  cvmax(opnex, 1);
541  opnex = 1;
542  if (opdiffuse) {
543  cvoverride(opnex, 1, PSD_FIX_OFF, PSD_EXIST_ON);
544  pinexnub = 0;
545  } else {
546  pinexnub = 3;
547  }
548  pinexval2 = 1;
549  pinexval3 = 1;
550  pinexval4 = 1;
551  pinexval5 = 1;
552  pinexval6 = 1;
553 
554  /* FOV */
555  opfov = 240;
556  pifovnub = 5;
557  pifovval2 = 200;
558  pifovval3 = 220;
559  pifovval4 = 240;
560  pifovval5 = 260;
561  pifovval6 = 280;
562 
563  /* phase FOV fraction */
564  opphasefov = 1;
565  piphasfovnub2 = 63;
566  piphasfovval2 = 1.0;
567  piphasfovval3 = 0.9;
568  piphasfovval4 = 0.8;
569  piphasfovval5 = 0.7;
570  piphasfovval6 = 0.6;
571 
572  /* freq (x) resolution */
573  cvmin(opxres, 16);
574 
575  /* phase (y) resolution */
576  cvmin(opyres, 16);
577 
578  if (KS_3D_SELECTED) {
579  /* assuming many shots for 3D */
580  cvdef(opxres, 320);
581  pixresnub = 63;
582  pixresval2 = 192;
583  pixresval3 = 256;
584  pixresval4 = 288;
585  pixresval5 = 320;
586  pixresval6 = 384;
587 
588  cvdef(opyres, 320);
589  piyresnub = 63;
590  piyresval2 = 192;
591  piyresval3 = 256;
592  piyresval4 = 288;
593  piyresval5 = 320;
594  piyresval6 = 384;
595  } else {
596  cvdef(opxres, 64);
597  cvdef(opyres, 64);
598  if (opdiffuse) {
599  pixresnub = 63;
600  pixresval2 = 96;
601  pixresval3 = 128;
602  pixresval4 = 160;
603  pixresval5 = 192;
604  pixresval6 = 224;
605 
606  piyresnub = 63;
607  piyresval2 = 96;
608  piyresval3 = 128;
609  piyresval4 = 160;
610  piyresval5 = 192;
611  piyresval6 = 224;
612  } else {
613  pixresnub = 63;
614  pixresval2 = 32;
615  pixresval3 = 64;
616  pixresval4 = 96;
617  pixresval5 = 128;
618  pixresval6 = 160;
619 
620  piyresnub = 63;
621  piyresval2 = 32;
622  piyresval3 = 64;
623  piyresval4 = 96;
624  piyresval5 = 128;
625  piyresval6 = 160;
626  }
627  }
628  opxres = _opxres.defval;
629  opyres = _opyres.defval;
630 
631 
632  /* Num echoes */
633  piechnub = 63;
634  cvdef(opnecho, 1);
635  cvmax(opnecho, 8);
636  opnecho = _opnecho.defval;
637  piechdefval = _opnecho.defval;
638  piechval2 = 1;
639  piechval3 = 2;
640  piechval4 = 4;
641  piechval5 = 6;
642  piechval6 = 8;
643 
644  /* ETL */
645  cvmax(opetl, 1024);
646  pietlnub = 0;
647 
648  /* TE */
649  avmaxte = 1s;
650  avminte = 0;
651  avminte2 = 0;
652  pitetype = PSD_LABEL_TE_EFF; /* alt. PSD_LABEL_TE_EFF */
653  cvdef(opte, 200ms);
654  opte = _opte.defval;
655  pite1nub = (opdiffuse) ? 6 : 63; /* 6: Only two menu choices MinTE & MinFullTE */
656  pite1val2 = PSD_MINIMUMTE;
657  pite1val3 = PSD_MINFULLTE;
658  pite1val4 = 30ms;
659  pite1val5 = 50ms;
660  pite1val6 = 70ms;
661 
662  /* TE2 */
663  /* pite2nub = 0; */
664 
665  /* TR */
666  cvdef(optr, 2s);
667  optr = _optr.defval;
668  if (opfast == TRUE) {
669  pitrnub = 0; /* '0': shown but greyed out (but only if opautotr = 1, otherwise TR menu is hidden) */
670  cvoverride(opautotr, PSD_ON, PSD_FIX_OFF, PSD_EXIST_ON);
671  } else {
672  pitrnub = 2; /* '2': only one menu choice (Minimum = AutoTR) */
673  }
674  pitrval2 = PSD_MINIMUMTR;
675 
676  /* FA */
677  if (acq_type == TYPSPIN) {
678  cvdef(opflip, 180); /* refocusing RF: initialize with low FA to avoid gradrf complaints on load */
679  pifanub = 0; /* can also be e.g. 2 to allow modification of refocusing flip angle */
680  pifamode = PSD_FLIP_ANGLE_MODE_REFOCUS;
681  pifaval2 = 180;
682  } else {
683  pifanub = 6;
684  pifamode = PSD_FLIP_ANGLE_MODE_EXCITE;
685  cvdef(opflip, 10);
686  pifaval2 = 10;
687  pifaval3 = 15;
688  pifaval4 = 20;
689  pifaval5 = 30;
690  pifaval6 = 90;
691  }
692  opflip = _opflip.defval;
693 
694 
695  /* slice thickness */
696  pistnub = 5;
697  if (!KS_3D_SELECTED) {
698  cvdef(opslthick, 4);
699  pistval2 = 3;
700  pistval3 = 4;
701  pistval4 = 5;
702  pistval5 = 6;
703  pistval6 = 10;
704  } else {
705  cvdef(opslthick, 2);
706  pistval2 = 1.50;
707  pistval3 = 1.75;
708  pistval4 = 2.00;
709  pistval5 = 2.25;
710  pistval6 = 2.50;
711  }
712  opslthick = _opslthick.defval;
713 
714  /* slice spacing */
715  cvdef(opslspace, 0);
716  pi_neg_sp = FALSE;
717  opslspace = _opslspace.defval;
718  piisil = FALSE;
719  piisnub = 0;
720  piisval2 = 0;
721 
722  /* default # of slices */
723  cvdef(opslquant, 30);
724 
725  /* 3D slice settings */
726  if (KS_3D_SELECTED) {/* PSD_3D (=2) or PSD_3DM (=6) */
727 
728  if (opimode == PSD_3DM) {
729  return KS_THROW("3D multislab mode not supported");
730  }
731 
732  if (acq_type == TYPSPIN) {
733  return KS_THROW("3D spin echo epi not supported");
734  }
735 
736  pimultislab = 0; /* 0: forces only single slab, 1: allow multi-slab */
737  pilocnub = 4;
738  pilocval2 = 32;
739  pilocval3 = 64;
740  pilocval4 = 128;
741  /* opslquant = #slices in slab. opvquant = #slabs */
742  cvdef(opslquant, 32);
743  }
744 
745  /* Multi phase (i.e. multi volumes) */
746  if (opmph) {
747  pimphscrn = 1; /* display Multi-Phase Parameter screen */
748  pifphasenub = 6;
749  pifphaseval2 = 10;
750  pifphaseval3 = 20;
751  pifphaseval4 = 50;
752  pifphaseval5 = 100;
753  pifphaseval6 = 200;
754  pisldelnub = 0;
755  /*
756  pisldelval3 = 1s;
757  pisldelval4 = 2s;
758  pisldelval5 = 5s;
759  pisldelval6 = 10s;
760  */
761  piacqnub = 0;
762  setexist(opacqo, 1);
763  pihrepnub = 0; /* no XRR gating */
764  } else {
765  if (!opdiffuse) {
766  cvoverride(opfphases, 1, PSD_FIX_OFF, PSD_EXIST_OFF);
767  }
768  pimphscrn = 0; /* do not display the Multi-Phase Parameter screen */
769  }
770 
771  if (KS_3D_SELECTED) {
772  pidefexcitemode = SELECTIVE;
773  piexcitemodenub = 1 + 2 /* + 4 FOCUS */;
774  cvdef(opexcitemode, SELECTIVE);
775  cvmax(opexcitemode, NON_SELECTIVE); /* 0=SELECTIVE, 1=NON_SELECTIVE */
776  }
777 
778 
779  /* Prescan buttons (autoshim). c.f. epic.h */
780  pipscoptnub = 1; /* Bit map of number of Prescan option buttons. 0=none, 1=autoshim, 2=phase corr */
781 
782  /* OPUSER_PSDVERSION: show GIT revision (GITSHA) using REV variable from the Imakefile */
783 #ifdef REV
784  char userstr[100];
785  sprintf(userstr, "PSD version: %s", REV);
786  cvset(OPUSER_PSDVERSION, 0, 0, 0, userstr);
787  piuset |= SHOW_RHRECON;
788 #endif
789 
790  /* ksepi_nover defaults depend on application (overridden by OPUSER_KYNOVER) */
791  if (opdiffuse) {
792  cvdef(ksepi_kynover,48); /* 48 lines drives up minTE, but results in better image quality for normal b-values */
793  } else if (acq_type == TYPGRAD) {
794  cvdef(ksepi_kynover,32); /* GE-EPI with long TE needs higher value to capture the less coherent k-space center (substantial image phase) */
795  } else {
796  cvdef(ksepi_kynover,16); /* SE-EPI has such distinct k-space peak with essentially no image phase, don't need many overscans */
797  }
798  /* OPUSER_KYNOVER: Number of overscans (extra kylines) for partial Fourier */
799  cvset(OPUSER_KYNOVER, _ksepi_kynover.minval, _ksepi_kynover.maxval, _ksepi_kynover.defval, _ksepi_kynover.descr);
800  piuset |= SHOW_KYNOVER;
801 
802  cvset(OPUSER_BLIPSIGN, _ksepi_blipsign.minval, _ksepi_blipsign.maxval, _ksepi_blipsign.defval, _ksepi_blipsign.descr);
804 
805  cvset(OPUSER_EPIREADOUTMODE, _ksepi_readout_mode.minval, _ksepi_readout_mode.maxval, _ksepi_readout_mode.defval, _ksepi_readout_mode.descr);
807 
808  /* OPUSER_FLEET_EPIREADOUTMODE for FLEET (used for GRAPPA calibration) */
809  cvset(OPUSER_FLEET_EPIREADOUTMODE, _ksepi_fleet_readout_mode.minval, _ksepi_fleet_readout_mode.maxval, _ksepi_fleet_readout_mode.defval, _ksepi_fleet_readout_mode.descr);
810  if (oparc && opaccel_ph_stride > 1 && !KS_3D_SELECTED) {
812  } else {
814  }
815 
816  /* OPUSER6_DIFF_RETURNMODE. Used by recon to determine what DICOM images to write out (bitmask: All:0 Acq:1 b0:2 DWI:4 ADC:8 Exp:16 FA:32 cFA:64) */
817  cvset(OPUSER6_DIFF_RETURNMODE, _ksepi_diffusion_returnmode.minval, _ksepi_diffusion_returnmode.maxval, _ksepi_diffusion_returnmode.defval, _ksepi_diffusion_returnmode.descr);
818  if (opdiffuse) {
820  } else {
822  }
823 
824  /* OPUSER7_SWI_RETURNMODE. Used by recon to determine what DICOM images to write out (bitmask: 0:Off 1:Acq 2:SWI 4:SWIphase) */
825  cvset(OPUSER7_SWI_RETURNMODE, _ksepi_swi_returnmode.minval, _ksepi_swi_returnmode.maxval, _ksepi_swi_returnmode.defval, _ksepi_swi_returnmode.descr);
826  if (oppseq != PSD_SE && KS_3D_SELECTED) { /* show for GE variants (PSD_GE, PSD_SPGR, ...) */
828  } else {
830  cvoverride(ksepi_swi_returnmode, 0, PSD_FIX_OFF, PSD_EXIST_OFF);
831  }
832 
833  /* OPUSER_REFLINES. Number of phase reference lines for ghost correction per shot */
834  cvdef(ksepi_reflines, 0);
835  ksepi_reflines = _ksepi_reflines.defval;
836  cvset(OPUSER_REFLINES, _ksepi_reflines.minval, _ksepi_reflines.maxval, _ksepi_reflines.defval, _ksepi_reflines.descr);
838 
839  if (KS_3D_SELECTED) {
840  cvset(OPUSER_KZACSLINES, _ksepi_kz_nacslines.minval, _ksepi_kz_nacslines.maxval, _ksepi_kz_nacslines.defval, _ksepi_kz_nacslines.descr);
842  } else {
844  }
845 
846  /*
847  Reserved opusers:
848  -----------------
849  ksepi_diffusion_predownload_setrecon(): opuser20-25 (needed by GE's recon)
850  GE reserves: opuser36-48 (epic.h)
851  */
852 
853 
854  /* Acceleration menu (max accel = 4). But we don't show ARC for 2D */
856 
857  /* multi-shot button (see also ksepi_eval_UI()) */
858  if (opdiffuse) {
859  pishotnub = 0;
860  } else {
861  pishotnub = 63;
862  }
863  if (KS_3D_SELECTED) {
864  pishotval2 = 8;
865  pishotval3 = 12;
866  pishotval4 = 16;
867  pishotval5 = 24;
868  pishotval6 = 32;
869  cvdef(opnshots, 16);
870 } else {
871  pishotval2 = 1;
872  pishotval3 = 2;
873  pishotval4 = 4;
874  pishotval5 = 8;
875  pishotval6 = 16;
876  cvdef(opnshots, 1);
877  }
878  cvmin(opnshots, 1);
879  cvmax(opnshots, 512);
880  opnshots = _opnshots.defval;
881 
882  /* Make R/L freq encoding attempts */
883  cvdef(opspf,1);
884  if (existcv(opplane) && (KS_PLANE_AX || KS_PLANE_COR)) {
885  piswapfc = 1;
886  cvmin(opspf,1);
887  if (existcv(opslquant) && existcv(opspf) && exist(opspf) == 0) {
888  return KS_THROW("Must choose FreqDir = R/L");
889  }
890  } else {
891  piswapfc = 0;
892  cvmin(opspf,0);
893  }
894 
895  /* Diffusion init */
896  status = ksepi_diffusion_init_UI();
897  KS_RAISE(status);
898 
899  return SUCCESS;
900 
901 } /* ksepi_init_UI() */
#define SHOW_RHRECON
Definition: ksepi_implementation.e:57
int piuset
#define SHOW_DIFF_RETURNMODE
Definition: ksepi_implementation.e:72
Definition: KSFoundation.h:2337
int opxres
#define SHOW_SWI_READOUTMODE
Definition: ksepi_implementation.e:75
int opyres
#define SHOW_KYNOVER
Definition: ksepi_implementation.e:60
#define OPUSER_REFLINES
Definition: ksepi_implementation.e:77
#define SHOW_FLEET_EPIREADOUTMODE
Definition: ksepi_implementation.e:69
#define KS_PLANE_AX
Definition: KSFoundation.h:245
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
#define OPUSER_FLEET_EPIREADOUTMODE
Definition: ksepi_implementation.e:68
#define OPUSER_KYNOVER
Definition: ksepi_implementation.e:59
#define OPUSER7_SWI_RETURNMODE
Definition: ksepi_implementation.e:74
#define SHOW_KZACSLINES
Definition: ksepi_implementation.e:81
#define OPUSER_PSDVERSION
Definition: ksepi_implementation.e:56
#define OPUSER_BLIPSIGN
Definition: ksepi_implementation.e:62
#define KS_PLANE_COR
Definition: KSFoundation.h:246
float ksepi_kissoff_factor
Definition: ksepi_implementation.e:201
#define OPUSER_EPIREADOUTMODE
Definition: ksepi_implementation.e:65
float opfov
#define KS_RAISE(status)
Definition: KSFoundation.h:190
#define SHOW_EPIREADOUTMODE
Definition: ksepi_implementation.e:66
#define cvset(cv, min, max, def, desc)
Definition: KSFoundation.h:2380
STATUS GEReq_init_accelUI(int integeraccel, int maxaccel)
Sets up the menu for parallel imaging (ARC or ASSET) with max/min range
Definition: GERequired.e:468
STATUS ksepi_diffusion_init_UI()
Initial setup of the diffusion part user interface (UI) with default values for menus and fields...
Definition: ksepi_implementation_diffusion.e:92
#define OPUSER6_DIFF_RETURNMODE
Definition: ksepi_implementation.e:71
#define SHOW_BLIPSIGN
Definition: ksepi_implementation.e:63
int ksepi_swi_returnmode
Definition: ksepi_implementation.e:266
int ksepi_kynover
Definition: ksepi_implementation.e:235
int ksepi_reflines
Definition: ksepi_implementation.e:261
#define SHOW_REFLINES
Definition: ksepi_implementation.e:78
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
float opslthick
_cvint _optr
int cfgcoiltype
#define OPUSER_KZACSLINES
Definition: ksepi_implementation.e:80

◆ ksepi_eval_UI()

STATUS ksepi_eval_UI ( )

Gets the current UI and checks for valid inputs

Return values
STATUSSUCCESS or FAILURE
924  {
925  STATUS status;
926 
927  status = ksepi_init_UI();
928  KS_RAISE(status);
929 
930  /*** Copy UserCVs to human readable CVs ***/
931  if (existcv(opautote) && opautote == PSD_MINTE) {
933  if (ksepi_kynover < _ksepi_kynover.minval || ksepi_kynover > _ksepi_kynover.maxval)
934  return KS_THROW("'#extralines for minTE' is out of range");
935  }
936 
939  return KS_THROW("The EPI blip sign must be either +1 or -1"); /* User error */
940  }
941 
943  if (ksepi_readout_mode < KS_EPI_BIPOLAR && ksepi_blipsign > KS_EPI_FLYBACK) {
944  return KS_THROW("Readout mode must be in range 0-2"); /* User error */
945  }
946 
948  if (ksepi_fleet_readout_mode < KS_EPI_BIPOLAR && ksepi_blipsign > KS_EPI_FLYBACK) {
949  return KS_THROW("FLEET readout mode must be in range 0-2"); /* User error */
950  }
951 
952  /* Reserved opusers:
953  -----------------
954  ksepi_diffusion_predownload_setrecon(): opuser20-25 (needed by GE's recon)
955  GE reserves: opuser36-48 (epic.h)
956  */
957 
958  cvoverride(opasset, FALSE, _opasset.fixedflag, _opasset.existflag); /* force asset off, but keep exist/fixed status */
959  piechnub = 63;
960 
962 
964 
965  ksepi_fleet = PLAY_FLEET; /* PLAY_FLEET is = 1 for 2D ARC R>1, otherwise 0 */
966 
968 
970 
971  return SUCCESS;
972 
973 } /* ksepi_eval_UI() */
int ksepi_diffusion_returnmode
Definition: ksepi_implementation_diffusion.e:59
int ksepi_fleet_readout_mode
Definition: ksepi_implementation.e:255
int ksepi_readout_mode
Definition: ksepi_implementation.e:239
#define OPUSER_REFLINES
Definition: ksepi_implementation.e:77
#define OPUSER_FLEET_EPIREADOUTMODE
Definition: ksepi_implementation.e:68
#define OPUSER_KYNOVER
Definition: ksepi_implementation.e:59
#define OPUSER7_SWI_RETURNMODE
Definition: ksepi_implementation.e:74
#define OPUSER_BLIPSIGN
Definition: ksepi_implementation.e:62
int ksepi_kz_nacslines
Definition: ksepi_implementation.e:237
#define OPUSER_EPIREADOUTMODE
Definition: ksepi_implementation.e:65
Definition: KSFoundation.h:2330
#define KS_RAISE(status)
Definition: KSFoundation.h:190
#define PLAY_FLEET
Definition: ksepi_implementation.e:52
int ksepi_blipsign
Definition: ksepi_implementation.e:233
#define OPUSER6_DIFF_RETURNMODE
Definition: ksepi_implementation.e:71
int ksepi_swi_returnmode
Definition: ksepi_implementation.e:266
int ksepi_kynover
Definition: ksepi_implementation.e:235
int ksepi_reflines
Definition: ksepi_implementation.e:261
STATUS ksepi_init_UI(void)
Initial setup of user interface (UI) with default values for menus and fields
Definition: ksepi_implementation.e:505
Definition: KSFoundation.h:2329
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
int ksepi_fleet
Definition: ksepi_implementation.e:250
Definition: KSFoundation.h:2330
#define OPUSER_KZACSLINES
Definition: ksepi_implementation.e:80

◆ ksepi_eval_setuprf()

STATUS ksepi_eval_setuprf ( )

Setup of selective RF excitation and refocusing designs and make of corresponding KS_SELRF

This function initializes the local excdesign and refdesign structures with default values and modifies them based on various CVs. The function then calls ks_eval_design_selrfexc() and ks_eval_design_selrfref() functions to evaluate the designs and store the results in ksepi.selrfexc and ksepi.selrfref structures respectively for later use in ksepi_pg()

Return values
STATUSSUCCESS or FAILURE
1052  {
1053 
1054  STATUS status;
1055 
1056  KS_SELRF_DESIGN excdesign = KS_INIT_SELRF_EXCDESIGN; /* c.f. ksdesign.h */
1057  KS_SELRF_DESIGN refdesign = KS_INIT_SELRF_REFDESIGN; /* c.f. ksdesign.h */
1058  strcpy(excdesign.description, "ksepimain.selrfexc");
1059  strcpy(refdesign.description, "ksepimain.selrfref");
1060 
1061  ksepi_gscalerfexc = (KS_3D_SELECTED) ? 1.0 : 0.9;
1062  ksepi_gscalerfref = (KS_3D_SELECTED) ? 1.0 : 0.9;
1063 
1064  excdesign.slthick = (KS_3D_SELECTED) ? (exist(opslquant) - 2 * pislblank) * exist(opslthick) : exist(opslthick);
1065  excdesign.flip = (acq_type == TYPSPIN) ? 90 : opflip;
1066  excdesign.gscale = ksepi_gscalerfexc;
1067  excdesign.rfstretch = ksepi_rfstretch_exc;
1068 
1069  if (KS_3D_SELECTED) { /* 3D */
1070  if (existcv(opexcitemode) && (opexcitemode == SELECTIVE)) { /* Selective 3D */
1071  /* N.B.: Select opslquant * opslthick >= 100 mm to get optimized RF pulses for 3D, otherwise
1072  the RF selection falls back to SPSP for 2D (ksdesign.cc) */
1074  } else { /* Non-selective 3D */
1075  excdesign.rfpulse_choice = EXC_HARD_LOWFAT;
1076  /* non-slice selective, set .slthick = 0 to have ks_**_selrf() produce a zero-amp gradient */
1077  excdesign.slthick = 0; /* Hard pulse w/o slice selection */
1078  }
1079  } else { /* 2D */
1080  excdesign.rfpulse_choice = (opfat) ? EXC_2D : EXC_SPSP;
1081  }
1082 
1083  status = ks_eval_design_selrfexc(&ksepi.selrfexc, excdesign); /* c.f. ksdesign.cc */
1084  KS_RAISE(status);
1085 
1086 
1087  /* selective RF refocusing */
1088  if (acq_type == TYPSPIN) {
1089  refdesign.slthick = exist(opslthick);
1090  refdesign.flip = opflip; /* pifamode = PSD_FLIP_ANGLE_MODE_REFOCUS when TYPSPIN */
1091  refdesign.gscale = ksepi_gscalerfref;
1092  refdesign.rfstretch = ksepi_rfstretch_ref;
1093  refdesign.rfpulse_choice = REF_SHARP_2D;
1096 
1097  status = ks_eval_design_selrfref(&ksepi.selrfref, refdesign); /* c.f. ksdesign.cc */
1098  KS_RAISE(status);
1099 
1100  } KS_RAISE(status);
1101 
1102  return SUCCESS;
1103 
1104 } /* ksepi_eval_setuprf() */
float ksepi_gscalerfref
Definition: ksepi_implementation.e:209
#define KS_INIT_SELRF_REFDESIGN
Definition: ksdesign.h:67
KS_SELRF selrfexc
Definition: ksepi_implementation.e:95
Input design to create a slice selective RF pulse. Should be a part of a sequence struct and set up b...
Definition: ksdesign.h:48
float rfstretch
Definition: ksdesign.h:53
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
int ksepi_fastexc3D
Definition: ksepi_implementation.e:203
#define KS_INIT_SELRF_EXCDESIGN
Definition: ksdesign.h:66
int bridge_crushers
Definition: ksdesign.h:55
float gscale
Definition: ksdesign.h:52
Definition: ksdesign.h:29
float flip
Definition: ksdesign.h:51
KS_SELRF selrfref
Definition: ksepi_implementation.e:96
Definition: ksdesign.h:29
float ksepi_rfstretch_ref
Definition: ksepi_implementation.e:210
int rfpulse_choice
Definition: ksdesign.h:58
Definition: ksdesign.h:30
float ksepi_crusher_dephasing
Definition: ksepi_implementation.e:208
#define KS_RAISE(status)
Definition: KSFoundation.h:190
Definition: ksdesign.h:29
float ksepi_rfstretch_exc
Definition: ksepi_implementation.e:202
Definition: ksdesign.h:29
float crusher_dephasing
Definition: ksdesign.h:54
int ksepi_bridgecrushers
Definition: ksepi_implementation.e:211
STATUS ks_eval_design_selrfref(KS_SELRF *selrfref, const KS_SELRF_DESIGN refdesign)
Function that sets up a KS_SELRF struct for selective RF refocusing based on an KS_SELRF_DESIGN
Definition: ksdesign.cc:367
float ksepi_gscalerfexc
Definition: ksepi_implementation.e:196
KS_DESCRIPTION description
Definition: ksdesign.h:49
float opslthick
float slthick
Definition: ksdesign.h:50
STATUS ks_eval_design_selrfexc(KS_SELRF *selrfexc, const KS_SELRF_DESIGN excdesign)
Function that sets up a KS_SELRF struct for selective RF excitation based on an KS_SELRF_DESIGN
Definition: ksdesign.cc:212
Definition: ksdesign.h:29

◆ ksepi_eval_setupfleet()

STATUS ksepi_eval_setupfleet ( )

Setup the components of the FLEET sequence (KSEPI_FLEET_SEQUENCE ksepi_fleetseq)

Based on CVs and by copying the .epitrain from the main sequence, this function sets up the sequence components of the FLEET sequence. The FLEET sequence is used for GRAPPA calibration in the recon (recon_ksepi2.m) for 2D scans. See C macro PLAY_FLEET in this file

Return values
STATUSSUCCESS or FAILURE
1119  {
1120  STATUS status;
1121 
1122  if (ksepi_fleet == FALSE) {
1123  return SUCCESS;
1124  }
1125 
1128  status = ks_eval_selrf1p(&ksepi_fleetseq.selrfexc, "fleetrfexc");
1129  KS_RAISE(status);
1130 
1131  /* EPI readout: First copy the EPI train from the main sequence */
1133 
1134  const int nshots = IMin(2, ksepi_fleet_num_ky, ksepi_fleet_nshots * ((ksepi_fleet_readout_mode != KS_EPI_BIPOLAR) ? 2 : 1));
1135  const int yres = nshots * CEIL_DIV(ksepi_fleet_num_ky, nshots);
1136  ksepi_fleetseq.epitrain.blipphaser.R = nshots; /* this many EPI interleaves to fill k-space */
1137  ksepi_fleetseq.epitrain.R_ky = 1; /* no undersampling (acceleration) */
1139  ksepi_fleetseq.epitrain.blipphaser.nover = 0; /* no partial Fourier for FLEET */
1140  ksepi_fleetseq.epitrain.epi_readout_mode = ksepi_fleet_readout_mode; /* KS_EPI_BIPOLAR, KS_EPI_FLYBACK, KS_EPI_SPLITODDEVEN */
1141 
1142  status = ks_eval_epi(&ksepi_fleetseq.epitrain, "epifleet", ks_qfact);
1143  KS_RAISE(status);
1144 
1146  status = ks_eval_trap(&ksepi_fleetseq.spoiler, "fleetspoiler");
1147  KS_RAISE(status);
1148 
1149  /* echo time shifting */
1152  if (ksepi_echotime_shifting_fleet == TRUE) {
1153  /*** Set up a pair of wait objects that are used to shift back the RF up to the echospacing ***/
1157  status = ks_eval_wait(&ksepi_fleetseq.pre_delay,"ksepi_fleet_wait_pre", GRAD_UPDATE_TIME, ksepi_echotime_shifting_sumdelay_fleet);
1158  KS_RAISE(status);
1160  KS_RAISE(status);
1161  }
1162 
1164  strcpy(ksepi_fleetseq.seqctrl.description, "ksepifleet");
1165 
1166  return SUCCESS;
1167 
1168 } /* ksepi_eval_setupfleet() */
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:114
STATUS ks_eval_selrf1p(KS_SELRF *selrf, const char *const desc) WARN_UNUSED_RESULT
Sets up a KS_SELRF object for RF slice selection with physical gradient constraints (invariant to sli...
Definition: KSFoundation_host.c:3339
int R
Definition: KSFoundation.h:1723
int ksepi_fleet_readout_mode
Definition: ksepi_implementation.e:255
int res
Definition: KSFoundation.h:1721
int R_ky
Definition: KSFoundation.h:1940
KS_SELRF selrfexc
Definition: ksepi_implementation.e:95
KS_WAIT pre_delay
Definition: ksepi_implementation.e:118
float ksepi_fleet_flip
Definition: ksepi_implementation.e:252
KS_PHASER blipphaser
Definition: KSFoundation.h:1937
float ksepi_spoilerarea
Definition: ksepi_implementation.e:198
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:302
KS_TRAP grad
Definition: KSFoundation.h:1561
float flip
Definition: KSFoundation.h:1028
KS_EPI epitrain
Definition: ksepi_implementation.e:92
float ks_qfact
Definition: GERequired.e:271
void ks_init_wait(KS_WAIT *wait)
Resets a KS_WAIT sequence object to its default value (KS_INIT_WAIT)
Definition: KSFoundation_host.c:70
void ks_init_seqcontrol(KS_SEQ_CONTROL *seqcontrol)
Resets KS_SEQ_CONTROL to its default value (KS_INIT_SEQ_CONTROL)
Definition: KSFoundation_host.c:148
int ksepi_fleet_nshots
Definition: ksepi_implementation.e:256
KS_RF rf
Definition: KSFoundation.h:1454
KS_TRAP spoiler
Definition: ksepi_implementation.e:116
KS_READTRAP read
Definition: KSFoundation.h:1932
int ksepi_echotime_shifting_fleet
Definition: ksepi_implementation.e:251
STATUS ks_eval_trap(KS_TRAP *trap, const char *const desc) WARN_UNUSED_RESULT
Sets up a trapezoid using a KS_TRAP sequence object with preset gradient constraints
Definition: KSFoundation_host.c:497
int ksepi_echotime_shifting_sumdelay_fleet
Definition: ksepi_implementation.e:321
int epi_readout_mode
Definition: KSFoundation.h:1939
float area
Definition: KSFoundation.h:670
#define KS_RAISE(status)
Definition: KSFoundation.h:190
KS_WAIT post_delay
Definition: ksepi_implementation.e:119
int nover
Definition: KSFoundation.h:1722
float ksepi_echotime_shifting_shotdelay_fleet
Definition: ksepi_implementation.e:317
Definition: KSFoundation.h:2329
STATUS ks_eval_wait(KS_WAIT *wait, const char *const desc, int pg_duration, int maxduration) WARN_UNUSED_RESULT
Sets up a wait pulse using a KS_WAIT sequence object
Definition: KSFoundation_host.c:281
KS_DESCRIPTION description
Definition: KSFoundation.h:1234
int read_spacing
Definition: KSFoundation.h:1942
int duration
Definition: KSFoundation.h:673
int ksepi_fleet
Definition: ksepi_implementation.e:250
KS_SELRF selrfexc
Definition: ksepi_implementation.e:117
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:4776
KS_EPI epitrain
Definition: ksepi_implementation.e:115
int ksepi_fleet_num_ky
Definition: ksepi_implementation.e:254

◆ ksepi_eval_setupobjects()

STATUS ksepi_eval_setupobjects ( )

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

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

Note that at the very end of this function, ksepi_eval_setupfleet() is called to also set up ksepi_fleetseq (KSEPI_FLEET_SEQUENCE) as well as ksepi (KSEPI_SEQUENCE) if ksepi_fleet is TRUE

Return values
STATUSSUCCESS or FAILURE
1186  {
1187  STATUS status;
1188 
1189  /* All RF related setup in separate function */
1190  status = ksepi_eval_setuprf();
1191  KS_RAISE(status);
1192 
1193 
1194  /* EPI readout */
1196  ksepi.epitrain.read.acq.rbw = oprbw;
1198  ksepi.epitrain.read.res = RUP_FACTOR(opxres, 2); /* round up (RUP) to nearest multiple of 2 */
1200  ksepi.epitrain.read.nover = 0; /* never partial Fourier in kx for EPI */
1201  ksepi.epitrain.blipphaser.fov = opfov * opphasefov;
1202  ksepi.epitrain.blipphaser.res = RUP_FACTOR((int) (opyres * opphasefov), 2); /* round up (RUP) to nearest multiple of 2 */
1203  ksepi.epitrain.blipphaser.nover = (opautote == PSD_MINTE) ? ksepi_kynover : 0; /* partial Fourier in ky */
1204  ksepi.epitrain.blipphaser.R = (opdiffuse || opnshots == 1) ? opaccel_ph_stride : opnshots; /* Number of shots to fully sample the desired part of k-space. opnshots hidden for diffusion */
1205  ksepi.epitrain.blipphaser.nacslines = 0; /* never have acs lines for EPI */
1206  ksepi.epitrain.R_ky = opaccel_ph_stride; /* actual acceleration is achieved by acquired a subset of shots */
1207  ksepi.epitrain.epi_readout_mode = ksepi_readout_mode; /* KS_EPI_BIPOLAR, KS_EPI_FLYBACK, KS_EPI_SPLITODDEVEN */
1208 
1209 
1210  /* z phase encoding gradient for the 3D case (one zphase enc. per TR, not real 3D EPI) */
1211  if (KS_3D_SELECTED) { /* PSD_3D or PSD_3DM */
1212  ksepi.epitrain.zphaser.fov = opvthick;
1213  ksepi.epitrain.zphaser.res = IMax(2, 1, opslquant);
1215  ksepi.epitrain.zphaser.R = opaccel_sl_stride;
1217  } else {
1218  ksepi.epitrain.zphaser.res = KS_NOTSET; /* ks_eval_epi will clear zphaser if res <= 1 */
1219  }
1220 
1221  /* EPI readout train */
1222  status = ks_eval_epi(&ksepi.epitrain, "epi", ksepi_epiqfact);
1223  KS_RAISE(status);
1224 
1225  /* echo time shifting */
1228 
1229  if (ksepi_echotime_shifting == TRUE) {
1230  /*** Set up a pair of wait objects that are used to shift back the RF up to the echospacing ***/
1232  ksepi_echotime_shifting_shotdelay = (float) epiesp / (float) ksepi.epitrain.blipphaser.R;
1234  status = ks_eval_wait(&ksepi.pre_delay,"ksepi_wait_pre", GRAD_UPDATE_TIME, ksepi_echotime_shifting_sumdelay);
1235  KS_RAISE(status);
1236  status = ks_eval_wait(&ksepi.post_delay,"ksepi_wait_post", ksepi_echotime_shifting_sumdelay - GRAD_UPDATE_TIME, ksepi_echotime_shifting_sumdelay);
1237  KS_RAISE(status);
1238  }
1239 
1240  if (ksepi_reflines > 0) {
1244 
1245  ksepi.dynreftrain.zphaser.res = KS_NOTSET; /* disable zphaser for reflines */
1246 
1247  status = ks_eval_epi(&ksepi.dynreftrain, "epireflines", ks_qfact);
1248  KS_RAISE(status);
1249 
1250  ks_init_phaser(&ksepi.dynreftrain.blipphaser); /* disable blipphaser for reflines */
1251  ks_init_trap(&ksepi.dynreftrain.blip); /* disable blips for reflines */
1252  }
1253  else {
1255  }
1256 
1257  /* Flow comp */
1260 
1261  if (opfcomp == TRUE) {
1262 
1263  if (ksepi_fcy) {
1264  /* Y: Need two extra phase gradients for flowcomp */
1265  status = ksepi_eval_flowcomp_phase(&ksepi.fcompphase, &ksepi.epitrain, "fcompphase");
1266  KS_RAISE(status);
1267  }
1268  if (ksepi_fcz) {
1269  /* Z: Add second z rephaser to complete 0th and 1st moment nulling of slice selection */
1271  status = ks_eval_trap(&ksepi.fcompslice, "fcompslice2");
1272  KS_RAISE(status);
1273 
1274  /* Z: Now, make normal z rephaser twice as large */
1275  ksepi.selrfexc.postgrad.area *= 2;
1276  status = ks_eval_trap(&ksepi.selrfexc.postgrad, "rfexc.reph_fc1");
1277  KS_RAISE(status);
1278  }
1279 
1280  } /* opfcomp */
1281 
1282 
1283  /* It is useful to be able to see the current echo spacing in DisplayCV to determine distortion levels etc */
1284  cvoverride(ksepi_esp, ksepi.epitrain.read.grad.duration + ksepi.epitrain.read_spacing, PSD_FIX_ON, PSD_EXIST_ON);
1285 
1286  /* for consistency, set opetl to the actual one for the EPI train even though ETL menu should never be visible for EPI */
1287  cvoverride(opetl, ksepi.epitrain.etl, PSD_FIX_ON, PSD_EXIST_ON);
1288 
1289 
1290  /* protect against too long sequence. It appears that opnecho * ksepi.epitrain.etl cannot be >= 1024 */
1291  if (ksepi.epitrain.etl * opnecho >= 1024) {
1292  return KS_THROW("# readouts >= 1024. Please reduce echoes, phase res. or increase NumShots");
1293  }
1294 
1295  /* post-read ksepi.spoiler */
1297  status = ks_eval_trap(&ksepi.spoiler, "spoiler");
1298  KS_RAISE(status);
1299 
1300  /* Diffusion */
1303  KS_RAISE(status);
1304 
1305  /* init seqctrl */
1307  strcpy(ksepi.seqctrl.description, "ksepimain");
1308 
1309  /* Setup FLEET sequence (returns early if ksepi_fleet = FALSE) */
1310  status = ksepi_eval_setupfleet();
1311  KS_RAISE(status);
1312 
1313  return SUCCESS;
1314 
1315 } /* ksepi_eval_setupobjects() */
KS_TRAP blip
Definition: KSFoundation.h:1935
STATUS ksepi_eval_diffusion(KSDIFF_CONTROL *diff_ctrl)
Creation of KSDIFF_CONTROL using a KSDIFF_CONTROL_DESIGN struct set by this function
Definition: ksepi_implementation_diffusion.e:413
int R
Definition: KSFoundation.h:1723
int res
Definition: KSFoundation.h:1721
int opxres
int R_ky
Definition: KSFoundation.h:1940
int ksepi_fcy
Definition: ksepi_implementation.e:244
int ksepi_readout_mode
Definition: ksepi_implementation.e:239
int nacslines
Definition: KSFoundation.h:1724
KS_SELRF selrfexc
Definition: ksepi_implementation.e:95
int opyres
KSDIFF_CONTROL ksepi_diffctrl
Definition: ksepi_implementation.e:299
#define KS_NOTSET
Definition: KSFoundation.h:115
int ksepi_echotime_shifting
Definition: ksepi_implementation.e:234
KS_TRAP fcompphase
Definition: ksepi_implementation.e:100
float fov
Definition: KSFoundation.h:1551
KS_PHASER blipphaser
Definition: KSFoundation.h:1937
float ksepi_spoilerarea
Definition: ksepi_implementation.e:198
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
float ksepi_echotime_shifting_shotdelay
Definition: ksepi_implementation.e:316
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
KS_EPI dynreftrain
Definition: ksepi_implementation.e:93
KS_PHASER zphaser
Definition: KSFoundation.h:1938
float rbw
Definition: KSFoundation.h:842
KS_TRAP grad
Definition: KSFoundation.h:1561
int ksepi_kznover
Definition: ksepi_implementation.e:236
int ksepi_fcz
Definition: ksepi_implementation.e:245
KS_EPI epitrain
Definition: ksepi_implementation.e:92
float ks_qfact
Definition: GERequired.e:271
void ks_init_wait(KS_WAIT *wait)
Resets a KS_WAIT sequence object to its default value (KS_INIT_WAIT)
Definition: KSFoundation_host.c:70
int etl
Definition: KSFoundation.h:1941
int ksepi_kz_nacslines
Definition: ksepi_implementation.e:237
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:91
void ks_init_seqcontrol(KS_SEQ_CONTROL *seqcontrol)
Resets KS_SEQ_CONTROL to its default value (KS_INIT_SEQ_CONTROL)
Definition: KSFoundation_host.c:148
void ks_init_trap(KS_TRAP *trap)
Resets a KS_TRAP sequence object to its default value (KS_INIT_TRAP)
Definition: KSFoundation_host.c:62
KS_TRAP fcompslice
Definition: ksepi_implementation.e:101
int res
Definition: KSFoundation.h:1552
KS_READTRAP read
Definition: KSFoundation.h:1932
STATUS ksepi_diffusion_eval_gradients_TE(KSEPI_SEQUENCE *epi, const KSDIFF_CONTROL *diff_ctrl)
Evaluate the diffusion gradients and TE
Definition: ksepi_implementation_diffusion.e:317
float opfov
STATUS ks_eval_trap(KS_TRAP *trap, const char *const desc) WARN_UNUSED_RESULT
Sets up a trapezoid using a KS_TRAP sequence object with preset gradient constraints
Definition: KSFoundation_host.c:497
int epi_readout_mode
Definition: KSFoundation.h:1939
float area
Definition: KSFoundation.h:670
int ksepi_esp
Definition: ksepi_implementation.e:228
#define KS_RAISE(status)
Definition: KSFoundation.h:190
KS_TRAP postgrad
Definition: KSFoundation.h:1464
int nover
Definition: KSFoundation.h:1722
KS_TRAP spoiler
Definition: ksepi_implementation.e:94
int ksepi_echotime_shifting_sumdelay
Definition: ksepi_implementation.e:320
int ksepi_kynover
Definition: ksepi_implementation.e:235
STATUS ksepi_eval_setuprf()
Setup of selective RF excitation and refocusing designs and make of corresponding KS_SELRF...
Definition: ksepi_implementation.e:1052
int ksepi_reflines
Definition: ksepi_implementation.e:261
float ksepi_epiqfact
Definition: ksepi_implementation.e:278
STATUS ks_eval_wait(KS_WAIT *wait, const char *const desc, int pg_duration, int maxduration) WARN_UNUSED_RESULT
Sets up a wait pulse using a KS_WAIT sequence object
Definition: KSFoundation_host.c:281
KS_DESCRIPTION description
Definition: KSFoundation.h:1234
int read_spacing
Definition: KSFoundation.h:1942
int ksepi_readlobegap
Definition: ksepi_implementation.e:223
int nover
Definition: KSFoundation.h:1554
int rampsampling
Definition: KSFoundation.h:1553
KS_READ acq
Definition: KSFoundation.h:1549
int duration
Definition: KSFoundation.h:673
void ks_init_epi(KS_EPI *epi)
Resets a KS_EPI sequence object to its default value (KS_INIT_EPI)
Definition: KSFoundation_host.c:126
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
STATUS ksepi_eval_setupfleet()
Setup the components of the FLEET sequence (KSEPI_FLEET_SEQUENCE ksepi_fleetseq)
Definition: ksepi_implementation.e:1119
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:4776
float fov
Definition: KSFoundation.h:1720
STATUS ksepi_eval_flowcomp_phase(KS_TRAP *fcphase, const KS_EPI *epi, const char *desc)
Evaluates the flow compensation gradient on the phase encoding (Y) board
Definition: ksepi_implementation.e:990
KS_WAIT pre_delay
Definition: ksepi_implementation.e:98
KS_WAIT post_delay
Definition: ksepi_implementation.e:99
void ks_init_phaser(KS_PHASER *phaser)
Resets a KS_PHASER sequence object to its default value (KS_INIT_PHASER)
Definition: KSFoundation_host.c:118
int ksepi_rampsampling
Definition: ksepi_implementation.e:222

◆ ksepi_eval_TErange()

STATUS ksepi_eval_TErange ( )

Sets the min 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 changes are made 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
1337  {
1338  int selrfend, min90_180, min180_echo;
1339 
1340  /* RF center to RF end */
1342 
1343  if (acq_type == TYPSPIN) {
1344 
1345  /* minimum TE: Spin-Echo EPI case (also diffusion) */
1346 
1347  /*** minimum time needed between RF exc center to RF ref center ***/
1348 
1349  /* RF center to rephaser end */
1350  min90_180 = selrfend + ksepi.selrfexc.postgrad.duration;
1351  if (ksepi_slicecheck == FALSE) { /* reflines dephaser may overlap with selrf rephaser unless slicecheck mode */
1353  }
1354  min90_180 += ksepi.dynreftrain.duration; /* end of reftrain */
1355 
1356  int diffusion_duration = 0;
1357  int i = 0;
1358  for (; i<3; ++i) {
1359  diffusion_duration = IMax(2, diffusion_duration, ksepi.diffgrads[i].duration);
1360  }
1361 
1362  if (opdiffuse) {
1363  min90_180 += diffusion_duration;
1364  } else if (ksepi_slicecheck == FALSE) {
1365  min90_180 -= IMin(2, ksepi.dynreftrain.readphaser.duration,
1366  ksepi.selrfref.grad2rf_start); /* reflines rephaser and selrefrf dephaser may overlap */
1367  }
1369 
1370  /*** minimum time needed between RF ref center and echo center ***/
1372  min180_echo += diffusion_duration; /* zero if not opdiffuse */
1373  min180_echo += ksepi.epitrain.time2center;
1374 
1375  if (ksepi_echotime_shifting == TRUE) {
1376  min180_echo += GRAD_UPDATE_TIME;
1377  }
1378 
1379  /* minimum TE is 2x the biggest of the two */
1380  avminte = IMax(2, min90_180, min180_echo) * 2;
1381 
1382  } else { /* GE-EPI */
1383 
1384  avminte = selrfend;
1385 
1386  if (ksepi_reflines > 0) {
1387  /* transports between selrf and reflines readout: */
1388  if (ksepi_slicecheck) {
1390  } else {
1391  avminte += IMax(2, ksepi.dynreftrain.readphaser.duration, /* X */
1393  }
1394  /* reflines readout: */
1396  /* transports between reflines readout and main epi readout: */
1397  avminte += IMax(3, ksepi.dynreftrain.readphaser.duration + ksepi.epitrain.readphaser.duration, /* X */
1399  ksepi.epitrain.zphaser.grad.duration) /* Z */;
1400  } else { /* no reflines */
1401  /* transports between selrf and main epi readout: */
1402  if (ksepi_slicecheck) {
1403  avminte += IMax(3, ksepi.epitrain.zphaser.grad.duration, /* X */
1406  } else {
1407  avminte += IMax(3, ksepi.epitrain.readphaser.duration, /* X */
1410  }
1411  }
1412 
1413  /* start of EPI readout */
1414  avminte -= IMax(3, ksepi.epitrain.readphaser.duration, /* X */
1416  ksepi.epitrain.zphaser.grad.duration) /* Z */;
1417  /* start of EPI train */
1418  avminte += ksepi.epitrain.time2center; /* minimum TE ! */
1419 
1420  if (ksepi_echotime_shifting == TRUE) {
1421  avminte += GRAD_UPDATE_TIME;
1422  }
1423  }
1424 
1425  avminte += GRAD_UPDATE_TIME * 2; /* 8us extra margin */
1426  avminte = RUP_FACTOR(avminte, 8); /* round up to make time divisible by 8us */
1427 
1428  avmaxte = avminte; /* initialization only to avoid avmaxte = 0 */
1429 
1430  /* time offset between two EPI trains (up to 16 echoes = EPI trains) */
1432 
1433 
1434  /* maximum TE */
1435  if (existcv(optr)) {
1436  if (opautotr) {
1437  /* TR = minTR, i.e. the current TE is also the maximum TE */
1438  if (opautote)
1439  avmaxte = avminte;
1440  else if (existcv(opte))
1441  avmaxte = opte;
1442  else
1443  avmaxte = avminte;
1444  } else {
1445  /* maximum TE dependent on the chosen TR */
1446  avmaxte = optr - ksepi.seqctrl.ssi_time; /* maximum sequence duration for this TR (implies one slice per TR) */
1447  avmaxte -= ksepi.spoiler.duration; /* subtract ksepi.spoiler time */
1449  if (opnecho > 1) {
1450  avmaxte -= (opnecho - 1) * ksepi_interechotime; /* for multi-echo */
1451  }
1452  }
1453  } else {
1454  avmaxte = 1s;
1455  }
1456 
1457  if (opnecho == 2) {
1458  /* for opnecho == 2, the TE2 button appears although we have greyed it out (pite2nub = 0).
1459  Make avminte2/opte2 contain the actual number */
1460  avminte2 = avminte + ksepi_interechotime;
1461  avmaxte2 = avmaxte + ksepi_interechotime;
1462  opte2 = opte + ksepi_interechotime;
1463  }
1464 
1465  if (opautote) {
1466  setpopup(opte, PSD_OFF);
1467  cvoverride(opte, avminte, PSD_FIX_ON, PSD_EXIST_ON); /* AutoTE: force TE to minimum */
1468  } else if (existcv(opte)) {
1469  setpopup(opte, PSD_ON);
1470  if (opte < avminte)
1471  return KS_THROW("TE=%.1f too small. Please increase TE to %.1f", opte / 1000.0, avminte / 1000.0);
1472  if (opte > avmaxte)
1473  return KS_THROW("TE=%.1f too large. Please decrease to %.1f", opte / 1000.0, avmaxte / 1000.0);
1474  } else {
1475  /* default value might be too low */
1476  opte = avminte;
1477  }
1478 
1479  return SUCCESS;
1480 
1481 } /* ksepi_eval_TErange() */
KS_TRAP grad
Definition: KSFoundation.h:1463
int start2iso
Definition: KSFoundation.h:1032
KS_TRAP grad
Definition: KSFoundation.h:1719
KS_SELRF selrfexc
Definition: ksepi_implementation.e:95
int ksepi_echotime_shifting
Definition: ksepi_implementation.e:234
KS_TRAP fcompphase
Definition: ksepi_implementation.e:100
KS_PHASER blipphaser
Definition: KSFoundation.h:1937
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
KS_EPI dynreftrain
Definition: ksepi_implementation.e:93
KS_PHASER zphaser
Definition: KSFoundation.h:1938
KS_EPI epitrain
Definition: ksepi_implementation.e:92
KS_TRAP pregrad
Definition: KSFoundation.h:1462
int duration
Definition: KSFoundation.h:1943
int grad2rf_start
Definition: KSFoundation.h:1466
int ksepi_interechotime
Definition: ksepi_implementation.e:313
#define KS_RFSSP_POSTTIME
Definition: KSFoundation.h:218
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:91
KS_RF rf
Definition: KSFoundation.h:1454
KS_SELRF selrfref
Definition: ksepi_implementation.e:96
KS_TRAP fcompslice
Definition: ksepi_implementation.e:101
KS_TRAP postgrad
Definition: KSFoundation.h:1464
int iso2end
Definition: KSFoundation.h:1033
int ssi_time
Definition: KSFoundation.h:1226
KS_TRAP spoiler
Definition: ksepi_implementation.e:94
int time2center
Definition: KSFoundation.h:1944
KS_TRAP readphaser
Definition: KSFoundation.h:1934
int ksepi_reflines
Definition: ksepi_implementation.e:261
int ksepi_echogap
Definition: ksepi_implementation.e:224
int rf2grad_end
Definition: KSFoundation.h:1467
int duration
Definition: KSFoundation.h:673
int ksepi_slicecheck
Definition: ksepi_implementation.e:197
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
KS_TRAP diffgrads[3]
Definition: ksepi_implementation.e:97
int ramptime
Definition: KSFoundation.h:671
#define KS_RFSSP_PRETIME
Definition: KSFoundation.h:217

◆ ksepi_set_kspace_design_forsat()

void ksepi_set_kspace_design_forsat ( KS_KSPACE_DESIGN kdesign)

Set the k-space design for use in the ksepi_eval_sat() function

ksepi_eval_sat()->kssat_setup_from_UI() (see ksmodules/kssat.e) needs a KS_KSPACE_DESIGN to get the FOV borders, why such struct is setup here. Ideally, this KS_KSPACE_DESIGN should also set up the proper fields of .epitrain field for the main sequence (ksepi), but this is for now still set up manually in ksepi_eval_setupobjects().

Note that all design structs are short-lived and are set up as a receipe for other structures to be used in pulsegen and scan

Parameters
[out]kdesignKS_KSPACE_DESIGN
Returns
void
1500  {
1501 
1502  /* k-space design */
1503  kdesign->res[XGRAD] = RUP_FACTOR(opxres, 2);
1504  kdesign->res[YGRAD] = RUP_FACTOR((int) (opyres * opphasefov), 2);
1505 
1506  kdesign->fov[XGRAD] = opfov;
1507  kdesign->fov[YGRAD] = opfov * opphasefov;
1508 
1509  kdesign->R[YGRAD] = (opdiffuse || opnshots == 1) ? opaccel_ph_stride : opnshots; /* Number of shots to fully sample the desired part of k-space. opnshots hidden for diffusion */
1510  kdesign->R_epi_ky = opaccel_ph_stride; /* undersampling in ky. R[YGRAD] must be equal to R_epi_ky for diffusion */
1511 
1512  kdesign->rbw = oprbw;
1513  kdesign->override_R1 = 0; /* If non-zero, override the analog receive gain with this value */
1514 
1515  kdesign->nover[YGRAD] = (opautote == PSD_MINTE) ? ksepi_kynover : 0; /* partial Fourier in ky */
1516  kdesign->nover[ZGRAD] = 0; /* always full Fourier in kz */
1517 
1518  if (KS_3D_SELECTED) {
1519  kdesign->res[ZGRAD] = opslquant;
1520  kdesign->fov[ZGRAD] = opslthick * kdesign->res[ZGRAD]; /* round zFOV to exactly match .res */
1521  kdesign->R[ZGRAD] = opaccel_sl_stride;
1522  }
1523 
1524  /* rampsampling on for ART (opsilent) */
1525  kdesign->rampsampling = (opsilent) ? TRUE : FALSE;
1526 
1527 } /* ksepi_set_kspace_design_forsat() */
int R_epi_ky
Definition: ksdesign.h:84
int opxres
int R[3]
Definition: ksdesign.h:83
int opyres
int nover[3]
Definition: ksdesign.h:82
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
float opfov
int override_R1
Definition: ksdesign.h:93
int ksepi_kynover
Definition: ksepi_implementation.e:235
float rbw
Definition: ksdesign.h:91
float opslthick
int rampsampling
Definition: ksdesign.h:81
int res[3]
Definition: ksdesign.h:80
float fov[3]
Definition: ksdesign.h:79

◆ ksepi_set_slicetiming_design()

void ksepi_set_slicetiming_design ( KS_SLICETIMING_DESIGN slicetiming_design)

Set up the number of slices, TR range, and min num acquisitions in KS_SLICETIMING_DESIGN

This function is called from ksepi_eval_loops()->ksepi_set_loop_control_design() to produce a KSSCAN_LOOP_CONTROL_DESIGN, which contains this KS_SLICETIMING_DESIGN struct steering how the final KS_SLICETIMING struct will be set up by ksscan_slicetiming_eval_design(), taking a KS_SLICETIMING_DESIGN as input

Note that all design structs are short-lived and are set up as a receipe for other structures to be used in pulsegen and scan

Parameters
[out]slicetiming_designKS_SLICETIMING_DESIGN to be created
Returns
void
1546  {
1547 
1548  /* interleaved slices in slice gap menu, force 2+ acqs */
1549  int minacqs = (opileave) ? 2 : 1;
1550 
1551  if (opslspace < 0) { /* Because we use overlap (pi_neg_sp) */
1552  minacqs = IMax(2, minacqs, ceil(opslthick / (opslthick - fabs(opslspace))));
1553  }
1554 
1555  slicetiming_design->is3D = KS_3D_SELECTED;
1556  slicetiming_design->nslices = opslquant;
1557  ksscan_copy_slices(slicetiming_design, ks_scan_info);
1558 
1559  slicetiming_design->minacqs = minacqs;
1560  if (opautotr) {
1561  slicetiming_design->minTR = 0;
1562  slicetiming_design->maxTR = 0;
1563  } else {
1564  slicetiming_design->minTR = optr;
1565  slicetiming_design->maxTR = optr;
1566  }
1567 
1568 } /* ksepi_set_slicetiming_design() */
void ksscan_copy_slices(KS_SLICETIMING_DESIGN *slicetiming_design, const SCAN_INFO *scan_info)
Copying of the graphical slice prescription in the UI (scan_info[]) and opslquant to the KS_SLICETIMI...
Definition: ksscan.cc:372
int minacqs
Definition: ksscan.h:26
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
int maxTR
Definition: ksscan.h:29
int nslices
Definition: ksscan.h:23
int is3D
Definition: ksscan.h:24
float opslthick
int minTR
Definition: ksscan.h:28
endif SCAN_INFO ks_scan_info[SLTAB_MAX]
Definition: GERequired.e:240

◆ ksepi_set_inversion_loop_control_design()

STATUS ksepi_set_inversion_loop_control_design ( KSINV_LOOP_CONTROL_DESIGN invloopctrl_design,
const KS_EPI epitrain 
)

Setup of a KSINV_LOOP_CONTROL_DESIGN with inversion related parameters

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

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

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

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

Note that all design structs are short-lived and are set up as a receipe for other structures to be used in pulsegen and scan

Parameters
[out]invloopctrl_designKSINV_LOOP_CONTROL_DESIGN to be created
[in]epitrainKS_EPI struct with .blipphaser and .zphaser fields steering the set of k-space coordinates to reach
Return values
STATUSSUCCESS or FAILURE
1658  {
1659 
1660  if (!ANYINVERSION) {
1661  invloopctrl_design->irmode = KSINV_OFF;
1662  return SUCCESS;
1663  }
1664 
1665  if (exist(opautotr) == 0 && existcv(optr)) {
1666  return KS_THROW("MinimumTR (Auto) must be selected for FLAIR");
1667  }
1668 
1669  if ((opirprep + opt1flair + opt2flair) > 1) {
1670  return KS_THROW("Mutually exclusive opirprep/opt1flair/opt2flair");
1671  }
1672 
1673  STATUS s = ksepi_set_loop_control_design(&invloopctrl_design->loopctrl_design, epitrain);
1674  KS_RAISE(s);
1675 
1676  invloopctrl_design->irmode = KSINV_OFF;
1677  ksepi_t1value_to_null = (cffield == 30000) ? T1_CSF_3T : T1_CSF_1_5T; /* default value */
1678 
1679  if (opirprep) { /* IR prep */
1680  ksepi_t1value_to_null = (cffield == 30000) ? T1_FAT_3T : T1_FAT_1_5T; /* default value */
1681  invloopctrl_design->dosliceahead = 1; /* TODO */
1682  invloopctrl_design->irmode = KSINV_ON_INTERLEAVED;
1683  }
1684  if (opt1flair) { /* interleaved IR */
1685  invloopctrl_design->dosliceahead = 1;
1686  invloopctrl_design->irmode = KSINV_ON_INTERLEAVED;
1689  }
1690  if (opt2flair) { /* FLAIR block */
1691  invloopctrl_design->irmode = KSINV_ON_FLAIR_BLOCK;
1693  }
1694 
1695  if (opautoti) { /* use either TI or T1value (XOR). Must set the non-used one to KS_NOTSET */
1696  invloopctrl_design->TI = KS_NOTSET;
1697  invloopctrl_design->T1value = ksepi_t1value_to_null;
1698  } else {
1699  invloopctrl_design->TI = opti;
1700  invloopctrl_design->T1value = KS_NOTSET;
1701  }
1702 
1703  return SUCCESS;
1704 
1705 } /* ksepi_set_inversion_loop_control_design() */
#define T1_FAT_3T
Definition: ksinversion.h:43
#define KS_NOTSET
Definition: KSFoundation.h:115
int ksepi_t1value_to_null
Definition: ksepi_implementation.e:216
int T1value
Definition: ksinversion.h:91
#define T1_CSF_1_5T
Definition: ksinversion.h:38
#define KSINV_MAXTR_T1FLAIR
Definition: ksinversion.h:35
Definition: ksinversion.h:27
STATUS ksepi_set_loop_control_design(KSSCAN_LOOP_CONTROL_DESIGN *loop_design, const KS_EPI *epitrain)
Setup of a KSSCAN_LOOP_CONTROL_DESIGN with desired k-space coordinates, averages, volumes...
Definition: ksepi_implementation.e:1593
KS_SLICETIMING_DESIGN slicetiming_design
Definition: ksscan.h:209
int irmode
Definition: ksinversion.h:89
#define KS_RAISE(status)
Definition: KSFoundation.h:190
Definition: ksinversion.h:27
Definition: ksinversion.h:27
#define T1_CSF_3T
Definition: ksinversion.h:37
#define T1_FAT_1_5T
Definition: ksinversion.h:44
int TI
Definition: ksinversion.h:90
#define KSINV_MINTR_T1FLAIR
Definition: ksinversion.h:34
#define KSINV_MINTR_T2FLAIR
Definition: ksinversion.h:33
#define ANYINVERSION
Definition: KSFoundation.h:346
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
int minTR
Definition: ksscan.h:28
KSSCAN_LOOP_CONTROL_DESIGN loopctrl_design
Definition: ksinversion.h:94
int dosliceahead
Definition: ksinversion.h:92

◆ ksepi_eval_inversion()

STATUS ksepi_eval_inversion ( KS_SEQ_COLLECTION seqcollection)

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

Note that all design structs are short-lived and are set up as a receipe for other structures to be used in pulsegen and scan. Here, the KSINV_DESIGN has local scope and is setup and used only by this function. What remains is the KSINV_MODULE ksepi_inv module, declaread in .

The KS_SEQ_COLLECTION is passed as a pointer to the function, to let the KSINV_MODULE to be registered in the collection for RF scaling, and heating calculations.

Parameters
[in,out]seqcollectionPointer to the KS_SEQ_COLLECTION struct holding all sequence modules
Return values
STATUSSUCCESS or FAILURE
1724  {
1725 
1726  STATUS status;
1727 
1728  KSINV_DESIGN inv_design = KSINV_INIT_DESIGN;
1729 
1730  ksinv_init_design(&inv_design, "inv"); /* e.g. STIR */
1731  if (opt1flair) {
1732  ksinv_init_design(&inv_design, "t1flair");
1733  }
1734  if (opt2flair) {
1735  ksinv_init_design(&inv_design, "t2flair");
1736  }
1737 
1738  inv_design.invdesign.slthick = opslthick;
1739  inv_design.invdesign.flip = 180.0;
1740  inv_design.invdesign.rfpulse_choice = INV_ADIABATIC; /* TODO */
1741  inv_design.spoiler_area = ksepi_spoilerarea;
1742  inv_design.gscale_policy = KSINV_GSCALE_NONOVERLAP; /* TODO */
1743  inv_design.slice_gap = opslspace;
1744  inv_design.ssi_time = ksepi_ssi_time;
1745 
1746  const int minacqs = (opileave) ? 2 : 1;
1747  status = ksinv_eval_design(&ksepi_inv, &inv_design, minacqs, seqcollection);
1748  KS_RAISE(status);
1749 
1750  return SUCCESS;
1751 
1752 } /* ksepi_eval_inversion() */
void ksinv_init_design(KSINV_DESIGN *design, const char *desc)
Resets the design of the standard inversion module
Definition: ksinversion.cc:31
float ksepi_spoilerarea
Definition: ksepi_implementation.e:198
Definition: ksdesign.h:31
float spoiler_area
Definition: ksinversion.h:61
float flip
Definition: ksdesign.h:51
int ssi_time
Definition: ksinversion.h:64
int rfpulse_choice
Definition: ksdesign.h:58
#define KSINV_INIT_DESIGN
Definition: ksinversion.h:67
int ksepi_ssi_time
Definition: ksepi_implementation.e:272
Definition: ksinversion.h:29
#define KS_RAISE(status)
Definition: KSFoundation.h:190
Design for the standard inversion module
Definition: ksinversion.h:56
int slice_gap
Definition: ksinversion.h:59
STATUS ksinv_eval_design(KSINV_MODULE *invseq, KSINV_DESIGN *invseq_design, int npasses, KS_SEQ_COLLECTION *seqcollection)
Standard setup function for KSINV_MODULE to be executed on HOST (cveval()) by the parent sequence (*...
Definition: ksinversion.cc:154
KS_SELRF_DESIGN invdesign
Definition: ksinversion.h:58
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:82
KSINV_MODULE ksepi_inv
Definition: ksepi_implementation.e:306
float opslthick
KSINV_GSCALE_POLICY gscale_policy
Definition: ksinversion.h:60
float slthick
Definition: ksdesign.h:50

◆ ksepi_eval_sat()

STATUS ksepi_eval_sat ( KS_SEQ_COLLECTION seqcollection)

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

As there can only be one global graphical saturation module that interacts with the UI, this function uses the global kssat struct (KSSAT_MODULE) in kssat.e, which is at the top of ksepi.e

seqcollection is passed as a pointer to the function, to register the KSSAT_MODULE in the collection for later RF scaling, and heating calculations.

Both design structs have local scope, and via ksepi_set_slicetiming_design(), the slice location info is used to control the location of the sat bands in kssat_setup_from_UI()

Parameters
[in,out]seqcollectionPointer to the KS_SEQ_COLLECTION struct holding all sequence modules
Return values
STATUSSUCCESS or FAILURE
1773  {
1774 
1775  STATUS status;
1776 
1779 
1781  ksepi_set_slicetiming_design(&slicetiming_design);
1782 
1783  status = kssat_setup_from_UI(&kssat,
1784  &kdesign,
1785  &slicetiming_design,
1786  opslthick,
1787  seqcollection);
1788  KS_RAISE(status);
1789 
1790  return SUCCESS;
1791 
1792 } /* ksepi_eval_sat() */
void ksepi_set_kspace_design_forsat(KS_KSPACE_DESIGN *kdesign)
Set the k-space design for use in the ksepi_eval_sat() function
Definition: ksepi_implementation.e:1500
STATUS kssat_setup_from_UI(KSSAT_MODULE *sat, KS_KSPACE_DESIGN *kspace_design, KS_SLICETIMING_DESIGN *slicetiming_design, float slthick, KS_SEQ_COLLECTION *seqcollection)
Setup the saturation module on the host from the scanner&#39;s UI
Definition: kssat.e:128
#define KS_INIT_SLICETIMING_DESIGN
Definition: ksscan.h:32
KSSAT_MODULE kssat
Definition: kssat.e:112
#define KS_INIT_KSPACE_2D_DESIGN
Definition: ksdesign.h:99
#define KS_RAISE(status)
Definition: KSFoundation.h:190
Input design for how to set up data acquistion (FOV, matrix size, parallel imaging, rBW etc)This struct is used by e.g. ks_eval_design_readtrap(), ksepi_eval_kdesign2epitrain(), ksfse_eval_numlines2acq() and is a part of all sequence generator&#39;s design structs (KSEPI_MODULE->KSEPI_DESIGN, KSFSE_MODULE->KSFSE_DESIGN, KSGRE_MODULE->KSGRE_DESIGN)
Definition: ksdesign.h:76
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:82
void ksepi_set_slicetiming_design(KS_SLICETIMING_DESIGN *slicetiming_design)
Set up the number of slices, TR range, and min num acquisitions in KS_SLICETIMING_DESIGN
Definition: ksepi_implementation.e:1546
Struct for desired slice timing and slice location behavior. To be filled in by a parent sequence bef...
Definition: ksscan.h:21
float opslthick

◆ ksepi_gradheat_play()

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

Play function of a test sequence used for gradient heating calculations

This function plays a set of sequence modules that collectively makes a test sequence that attempts to be a good approximation of the average and maxmimum power dissipation of the gradient system. This function is not used for any data collection.

This function first plays the saturation sequence (if kssat.seqctrl.duration > 0), then the inversion sequence (if any), then, if diffusion, scaled versions of the diffusion gradients are played (either .RMS_amp_scale or .max_power_amp_scale), with the main sequence based on the max_encode_mode.

It should be noted that the content of this function is manual work and needs to be updated if the content of ksepi_pg() or used sequence modules are changed for the gradient heating to be accurate. So if, for example, major dynamic changes of gradient amplitudes or which sequence modules that are used, this function should be updated accordingly.

This function is passed as an argument to ks_eval_getduration() to get the playout time and to ks_eval_hwlimits() to get the new minimum time due to hardware heating and SAR calculations.

As ks_eval_getduration() and ks_eval_hwlimits() are common for all psds, this function has to have nargs and args as input arguments, but they are not used here. See ksepi_eval_loops() for more details.

Parameters
max_encode_modeThe maximum encoding mode, which can be either AVERAGE_POWER or MAXIMUM_POWER.
[in]nargs(not used) Number of extra input arguments (# elements of void pointer array **args)
[in]args(not used) Void pointer array with nargs elements (may be NULL)
Return values
STATUSSUCCESS or FAILURE
1826  {
1827  (void) nargs;
1828  (void) args;
1829 
1830  int j;
1831 
1832  /* Sat */
1834 
1835  /* Inversion */
1836  if (ANYINVERSION) {
1838  }
1839 
1840  /* main */
1841  if (max_encode_mode == AVERAGE_POWER) {
1842 
1845 
1846  /* RMS over all diffusion directions for each board */
1847  for (j = 0; j < 3; ++j) {
1849  }
1850  } else { /* MAXIMUM_POWER */
1851 
1854 
1855  /* X diffusion direction is usually the worst case */
1856  for (j = 0; j < 3; ++j) {
1858  }
1859  }
1861 
1862  return SUCCESS;
1863 
1864 } /* ksepi_gradheat_play() */
KS_SEQ_CONTROL seqctrl
Definition: kssat.e:53
void ks_scan_phaser_max(KS_PHASER *phaser, int instanceno)
ADDTITLEHERE
Definition: KSFoundation_tgt.c:497
void ks_scan_trap_ampscale(KS_TRAP *trap, int instanceno, float ampscale)
Updates the amplitude of one or all instances of a KS_TRAP sequence object
Definition: KSFoundation_tgt.c:306
KSDIFF_CONTROL ksepi_diffctrl
Definition: ksepi_implementation.e:299
KS_PHASER blipphaser
Definition: KSFoundation.h:1937
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
float max_power_amp_scale[3]
Definition: ksdiffusion.h:52
KS_PHASER zphaser
Definition: KSFoundation.h:1938
KS_EPI epitrain
Definition: ksepi_implementation.e:92
float RMS_amp_scale[3]
Definition: ksdiffusion.h:51
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:91
KSSAT_MODULE kssat
Definition: kssat.e:112
int ks_scan_playsequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1644
#define ANYINVERSION
Definition: KSFoundation.h:346
void ks_scan_phaser_average(KS_PHASER *phaser, int instanceno)
ADDTITLEHERE
Definition: KSFoundation_tgt.c:490
KSINV_MODULE ksepi_inv
Definition: ksepi_implementation.e:306
KS_TRAP diffgrads[3]
Definition: ksepi_implementation.e:97
KS_SEQ_CONTROL seqctrl
Definition: ksinversion.h:73

◆ ksepi_eval_loops()

STATUS ksepi_eval_loops ( KS_SEQ_COLLECTION seqcollection)

Setup of scan loop control structs (main and FLEET sequences) after heating calculations

This function performs the following tasks:

Note that all design structs are short-lived and are set up as a receipe for other structures to be used in pulsegen and scan. Here this applies to the local variables fleet_loopctrl_design, loopctrl_design, and inv_loopctrl_design.

Parameters
[in,out]seqcollectionPointer to the KS_SEQ_COLLECTION struct holding all sequence modules
Return values
STATUSSUCCESS or FAILURE
1890  {
1891 
1892  STATUS status;
1893 
1894  /* SAR and gradient heating */
1895  const int time = ks_eval_getduration(seqcollection, ksepi_gradheat_play, 0, NULL);
1896 
1897  int newtime = 0;
1898  status = ks_eval_hwlimits(&newtime, seqcollection, &loggrd, ksepi_gradheat_play, 0, NULL);
1899  KS_RAISE(status);
1900 
1901  if (newtime > time) {
1902  ks_dbg("gradheat time: %d -> %d", time, newtime);
1904  }
1905 
1906  /* FLEET loop control */
1908  /* ksepi_set_loop_control_design() as for main, but override some fields in the next few lines */
1909  status = ksepi_set_loop_control_design(&fleet_loopctrl_design, &ksepi_fleetseq.epitrain);
1910  KS_RAISE(status);
1911  fleet_loopctrl_design.dda = IMax(2, 1, ksepi_fleet_dda); /* safety net to ensure at least one dummy for FLEET (for Nyquist ghost correction in recon_ksepi2.m) */
1912  fleet_loopctrl_design.naverages = 1;
1913  fleet_loopctrl_design.nvols = 1;
1914  fleet_loopctrl_design.slicetiming_design.minacqs = fleet_loopctrl_design.slicetiming_design.nslices; /* Sequential */
1915  fleet_loopctrl_design.slicetiming_design.minTR = 0;
1916  fleet_loopctrl_design.slicetiming_design.maxTR = 0;
1917 
1921  &fleet_loopctrl_design);
1922  KS_RAISE(status);
1923 
1924 
1925  /* Main or Inversion loop control */
1926  if (!ANYINVERSION) {
1928  status = ksepi_set_loop_control_design(&loopctrl_design, &ksepi.epitrain);
1929  KS_RAISE(status);
1930 
1932  &ksepi.seqctrl,
1934  &loopctrl_design);
1935  KS_RAISE(status);
1936  } else {
1938  ksepi_set_inversion_loop_control_design(&inv_loopctrl_design, &ksepi.epitrain);
1939 
1943  &inv_loopctrl_design,
1944  seqcollection);
1945  KS_RAISE(status);
1946  }
1947 
1948  /* Fill in the 'tmin' and 'tmin_total'. tmin_total is only like GEs use of the variable when TR = minTR */
1949  tmin = ksepi.seqctrl.min_duration;
1950  tmin_total = ksepi.seqctrl.duration;
1951 
1952  return SUCCESS;
1953 
1954 } /* ksepi_eval_loops() */
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:114
int minacqs
Definition: ksscan.h:26
Design parameters for generating a KSSCAN_LOOP_CONTROL
Definition: ksscan.h:201
int naverages
Definition: ksscan.h:204
#define KSINV_INIT_LOOP_CONTROL_DESIGN
Definition: ksinversion.h:97
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
int ksepi_fleet_dda
Definition: ksepi_implementation.e:253
STATUS ksepi_gradheat_play(const INT max_encode_mode, int nargs, void **args)
Play function of a test sequence used for gradient heating calculations
Definition: ksepi_implementation.e:1826
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:302
int duration
Definition: KSFoundation.h:1227
KSINV_LOOP_CONTROL ksepi_inv_loopctrl
Definition: ksepi_implementation.e:307
KS_EPI epitrain
Definition: ksepi_implementation.e:92
KS_CORESLICETIME ksepi_scan_irslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Wrapper function to ksinv_scan_irslice() with ksepi_inv (global in this file) as argument
Definition: ksepi_implementation.e:2942
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:91
STATUS ks_eval_hwlimits(int *newtime, KS_SEQ_COLLECTION *seqcollection, const LOG_GRAD *log_grad, STATUS(*play)(const INT max_encode_mode, int nargs, void **args), int nargs, void **args)
Definition: KSFoundation_host.c:5848
int dda
Definition: ksscan.h:202
LOG_GRAD loggrd
int nvols
Definition: ksscan.h:203
int min_duration
Definition: KSFoundation.h:1224
STATUS ksepi_set_loop_control_design(KSSCAN_LOOP_CONTROL_DESIGN *loop_design, const KS_EPI *epitrain)
Setup of a KSSCAN_LOOP_CONTROL_DESIGN with desired k-space coordinates, averages, volumes...
Definition: ksepi_implementation.e:1593
KS_SLICETIMING_DESIGN slicetiming_design
Definition: ksscan.h:209
Design for KSINV_LOOP_CONTROL
Definition: ksinversion.h:88
STATUS ksscan_loop_control_eval_design(KSSCAN_LOOP_CONTROL *loop_control, KS_SEQ_CONTROL *sequence_to_inflate, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), const KSSCAN_LOOP_CONTROL_DESIGN *design)
Generates a loop control
Definition: ksscan.cc:110
STATUS ks_eval_seqctrl_setduration(KS_SEQ_CONTROL *seqctrl, int dur)
Sets the .duration field of the sequence module (KS_SEQ_CONTROL), while checking that the input value...
Definition: KSFoundation_host.c:4952
#define KS_RAISE(status)
Definition: KSFoundation.h:190
STATUS ksepi_set_inversion_loop_control_design(KSINV_LOOP_CONTROL_DESIGN *invloopctrl_design, const KS_EPI *epitrain)
Setup of a KSINV_LOOP_CONTROL_DESIGN with inversion related parameters
Definition: ksepi_implementation.e:1658
KSSCAN_LOOP_CONTROL ksepi_loopctrl
Definition: ksepi_implementation.e:298
int maxTR
Definition: ksscan.h:29
KSSCAN_LOOP_CONTROL ksepi_fleet_loopctrl
Definition: ksepi_implementation.e:303
STATUS ksinv_loop_control_eval_design(KSINV_LOOP_CONTROL *inv_loopctrl, KS_CORESLICETIME irslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), KS_SEQ_CONTROL *invseq_seqctrl_ptr, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), KS_SEQ_CONTROL *mainseq_seqctrl_ptr, const KSINV_LOOP_CONTROL_DESIGN *design, KS_SEQ_COLLECTION *seqcollection)
Generate an inversion loop control given both custom core acquisition and inversion
Definition: ksinversion.cc:202
int nslices
Definition: ksscan.h:23
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:82
STATUS STATUS ks_dbg(const char *format,...) __attribute__((format(printf
Common debug message function for HOST and TGT
KS_CORESLICETIME ksepi_scan_coreslicegroup(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Function to run for scan to execute one slice of the ksepi sequence module with optional sat module...
Definition: ksepi_implementation.e:3081
#define ANYINVERSION
Definition: KSFoundation.h:346
KSINV_MODULE ksepi_inv
Definition: ksepi_implementation.e:306
int minTR
Definition: ksscan.h:28
KS_CORESLICETIME ksepi_scan_fleet_coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Plays out one slice for the ksepi_fleetseq sequence module in real time during scanning
Definition: ksepi_implementation.e:3114
KS_SEQ_CONTROL seqctrl
Definition: ksinversion.h:73
s64 ks_eval_getduration(KS_SEQ_COLLECTION *seqcollection, STATUS(*play)(const INT max_encode_mode, int nargs, void **args), int nargs, void **args)
Definition: KSFoundation_host.c:5879
KS_EPI epitrain
Definition: ksepi_implementation.e:115
#define KSSCAN_INIT_LOOP_CONTROL_DESIGN
Definition: ksscan.h:211

◆ ksepi_eval_ssitime()

int ksepi_eval_ssitime ( )

The SSI time for the sequence

Returns
int SSI time in [us]
1965  {
1966 
1967  /* SSI time CV:
1968  Empirical finding on how much SSI time we need to update.
1969  But, use a longer SSI time when we write out data to file in scan() */
1970  ksepi_ssi_time = RUP_GRD(IMax(2,
1972  _ksepi_ssi_time.minval));
1973 
1974  /* Copy SSI CV to seqctrl field used by setssitime() */
1975  ksepi.seqctrl.ssi_time = RUP_GRD(ksepi_ssi_time);
1977 
1978  /* SSI time one-sequence-off workaround:
1979  We set the hardware ssitime in ks_scan_playsequence(), but it acts on the next sequence module, hence
1980  we aren't doing this correctly when using multiple sequence modules (as KSChemSat etc).
1981  One option would be to add a short dummy sequence ks_scan_playsequence(), but need to investigate
1982  if there is a better way. For now, let's assume the the necessary update time is the longest for
1983  the main sequence (this function), and let the ssi time for all other sequence modules (KSChemSat etc)
1984  have the same ssi time as the main sequence. */
1986 
1987  return ksepi_ssi_time;
1988 
1989 } /* ksepi_eval_ssitime() */
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:114
#define KSEPI_DEFAULT_SSI_TIME_ICEHARDWARE
Definition: ksepi_implementation.e:45
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:302
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:91
#define KSEPI_DEFAULT_SSI_TIME
Definition: ksepi_implementation.e:46
int ksepi_ssi_time
Definition: ksepi_implementation.e:272
int ks_syslimits_hasICEhardware()
Check for ICE Hardware (e.g. RX27+ on SIGNA Premier)
Definition: KSFoundation_common.c:215
int ssi_time
Definition: KSFoundation.h:1226
int kssat_ssi_time
Definition: kssat.e:118

◆ ksepi_eval_scantime()

STATUS ksepi_eval_scantime ( KS_SEQ_COLLECTION seqcollection)

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

pitscan is the UI variable for the scan clock shown in the top right corner on the MR scanner. The call to GEReq_eval_checkTR_SAR_calcs() also sets up the UI SAR annotation.

Return values
STATUSSUCCESS or FAILURE
2003  {
2004 
2005  STATUS status;
2006 
2007  /* Step 1: set all `seqctrl.nseqinstances` to 0 */
2009 
2010  /* Step 2: run the scan loop to get total scan time */
2011  n64 scantime = ksepi_scan_scanloop();
2012 
2013  /* Step 3: Check that the entire sequence (across all sequence modules) is within SAR & hardware limits.
2014  Also sets up UI SAR annotation */
2015  status = GEReq_eval_checkTR_SAR_calcs(seqcollection, scantime);
2016  KS_RAISE(status);
2017 
2018  pitscan = (float) scantime; /* Scan time clock in UI */
2019 
2020  return SUCCESS;
2021 
2022 } /* ksepi_eval_scantime() */
#define KS_RAISE(status)
Definition: KSFoundation.h:190
s64 ksepi_scan_scanloop()
Plays out all volumes and passes of a single or multi-pass scan
Definition: ksepi_implementation.e:3180
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:82
void ks_eval_seqcollection_resetninst(KS_SEQ_COLLECTION *seqcollection)
Set the .nseqinstances field of each sequence module (KS_SEQ_CONTROL) equal to 0
Definition: KSFoundation_host.c:5929
STATUS GEReq_eval_checkTR_SAR_calcs(KS_SEQ_COLLECTION *seqcollection, s64 intended_time)
Checks that sequence modules sum up to TR, honoring SAR/heating limits
Definition: GERequired.e:902

◆ ksepi_update_UI()

STATUS ksepi_update_UI ( )

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

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

Return values
STATUSSUCCESS or FAILURE
2045  {
2046 
2047  /* Force the user to select the Echo Planar Imaging button. This error needs to be in cvcheck(), not in
2048  cvinit()/cveval() to avoid it to trigger also when Echo Planar Imaging has been selected.
2049  Without opepi = 1, the images won't show up correctly in the GE DB after the 1st volume */
2050 
2051  if (!KS_3D_SELECTED && opepi == PSD_OFF) {
2052  return KS_THROW("Please first select the 'Echo Planar Imaging' button");
2053  }
2054 
2055  if (existcv(opte) && existcv(opnex) && opautote == PSD_MINTE && opnex < 1.0) {
2056  return KS_THROW("TE = MinTE and NEX < 1 is not allowed");
2057  }
2058 
2059  if (ksepi_reflines > ksepi.epitrain.etl) {
2060  return KS_THROW("ksepi_reflines cannot be larger than echo train length");
2061  }
2062 
2063  if (existcv(opnshots) && (opasset == ASSET_SCAN) && (opnshots > 1)) {
2064  return KS_THROW("ASSET not compatible with multishot");
2065  }
2066 
2067  if (opasset != 0 && opasset != ASSET_SCAN) {
2068  return KS_THROW("ASSET flag must be either 0 (OFF) or 2 (ON)");
2069  }
2070 
2071  if (opdiffuse && oppseq == 2) {
2072  return KS_THROW("Select SpinEcho for Diffusion");
2073  }
2074 
2075 
2076  const KSSCAN_LOOP_CONTROL *loopctrl = ksepi_get_loop_ctrl();
2077 
2078  _optr.minval = 0;
2079  _optr.maxval = 60s;
2080  if (opautotr) {
2081  avmintr = loopctrl->slicetiming.TR;
2082  avmaxtr = loopctrl->slicetiming.TR;
2083  } else {
2084  avmintr = _optr.minval;
2085  avmaxtr = _optr.maxval;
2086  }
2087  (optr) = loopctrl->slicetiming.TR; /* ()-parentheses avoids fixedflag expansion */
2088  act_tr = loopctrl->slicetiming.TR;
2089  ihtr = optr; /* image header TR */
2090 
2091  /* show max slices/TR and # acqusitions */
2092  (avmaxslquant) = loopctrl->slicetiming.maxslices_per_TR;
2093  (avmaxacqs) = loopctrl->slicetiming.slice_plan.npasses;
2094 
2095 
2096  /* Pixel size in UI */
2097  piinplaneres = 1;
2098  ihinplanexres = opfov / ksepi.epitrain.read.res;
2099  ihinplaneyres = (opfov * opphasefov) / ksepi.epitrain.blipphaser.res;
2100 
2101  /* show echo spacing in UI */
2102  piesp = 1;
2103  ihesp = ksepi.epitrain.read.grad.duration / 1000.0;
2104 
2105  return SUCCESS;
2106 
2107 } /* ksepi_update_UI() */
int res
Definition: KSFoundation.h:1721
KS_SLICETIMING slicetiming
Definition: ksscan.h:192
KS_PHASER blipphaser
Definition: KSFoundation.h:1937
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
KS_TRAP grad
Definition: KSFoundation.h:1561
KS_EPI epitrain
Definition: ksepi_implementation.e:92
int etl
Definition: KSFoundation.h:1941
int TR
Definition: ksscan.h:43
int res
Definition: KSFoundation.h:1552
int npasses
Definition: KSFoundation.h:1319
ifndef ACT_TR_EXISTS int act_tr
Definition: GERequired.e:235
KS_READTRAP read
Definition: KSFoundation.h:1932
float opfov
Structure containing all the information to perform a standard scan loop
Definition: ksscan.h:184
int ksepi_reflines
Definition: ksepi_implementation.e:261
int maxslices_per_TR
Definition: ksscan.h:44
int duration
Definition: KSFoundation.h:673
const KSSCAN_LOOP_CONTROL * ksepi_get_loop_ctrl()
Function to automatically switch between inverision and standard loop control
Definition: ksepi_implementation.e:2300
KS_SLICE_PLAN slice_plan
Definition: ksscan.h:42
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
_cvint _optr

◆ ksepi_predownload_plot()

STATUS ksepi_predownload_plot ( KS_SEQ_COLLECTION seqcollection)

Plotting of sequence modules and slice timing in HTML files

If a file /usr/g/research/bin/ksdonotplot exists, this function will return SUCCESS without plotting. This is a system-wide way of quickly disabling plotting for all sequences.

Otherwise the function first prints out the textfile: <ks_psdname>_objects.txt, which contains the specs of most sequence components in the sequence.

The rest of the function is the plotting the main and FLEET sequence diagrams as HTML files, and lastly the sequence timing plot, showing slice location on the y-axis and time on the x-axis for all sequence modules at the same time.

The HTML plots will have a slider to show the dynamics of a psd. What is interesting to show dynamics for can vary between psds. If diffusion is on, only the diffusion scheme index should be changed by the slider, otherwise the shot index should be changed. To do this, this function must play the relevant changes that should be presented in the HTML plot slider and skip non-relevant changes such as change in slice location. One can think of this as recording something in a video, where only the relevant parts are recorded.

"Recording" is first reset by ks_eval_seqcollection_resetninst(). Then, for diffsion, a call to ksdiff_plotloop() is made to play a single slice and shot index for many diffusion scheme indices. For non-diffusion, the generic ksscan_plotloop_shots() is used to play a single slice for many shot indices.

Note that ksscan_plotloop_shots() internally copies the loop_control struct (arg 2) and overrides the number of slices in order to play a single slice.

Lastly, ks_plot_psd() is called to write out a JSON file, followed by a system call to the python script psdplot/psdplot.py to create the HTML plots. The HTML files can take 10-20 s to generate, so be patient.

The FLEET sequence is recorded using ksscan_plotloop_shots(), to show shot-to-shot variations with the HTML plot slider.

For the slicetiming plot, the three functions ks_plot_slicetime_begin();ksepi_scan_scanloop();ks_plot_slicetime_end(); creates a corresponding JSON file, followed by a system call to the python script psdplot/psdplot_slicetime.py to create the HTML plot.

Return values
STATUSSUCCESS or FAILURE
2160  {
2161  char tmpstr[1000];
2162 
2163  /* System wide (psd independent) option to disable plotting, to e.g. speed up UX on a slow MR show system */
2164  if (existfile("/usr/g/research/bin/ksdonotplot")) {
2165  return SUCCESS;
2166  }
2167 
2168 
2169 #ifdef PSD_HW
2170  sprintf(tmpstr, "/usr/g/mrraw/%s_objects.txt", ks_psdname);
2171 #else
2172  sprintf(tmpstr, "./%s_objects.txt", ks_psdname);
2173 #endif
2174  FILE *fp = fopen(tmpstr, "w");
2175 
2176  /* Note: 'fp' can be replaced with 'stdout' or 'stderr' to get these
2177  values printed out in the WTools window in simulation. However,
2178  heavy printing may result in that the WTools window closes,
2179  why we here write to a file ksepi_objects.txt instead */
2182  int i = 0;
2183  for (; i<3; ++i) {
2184  ks_print_trap(ksepi.diffgrads[i], fp); /* opdiffuse = 1 */
2185  }
2189  fclose(fp);
2190 
2191 
2193 
2194  /* MAIN */
2195  if (opdiffuse) {
2196  ksdiff_schemeloop(&ksepi_diffctrl, ksepi_get_loop_ctrl(), NULL, ksepi_scan_coreslicegroup); /* HTML plot slider will change the diffusion scheme index */
2198  } else {
2199  ksscan_plotloop_shots(ksepi_get_loop_ctrl(), ksepi_scan_coreslicegroup); /* HTML plot slider will change the shot index */
2200  }
2202 
2203  /* FLEET */
2206 
2207  /* Saturation */
2209 
2210  /* Sequence timing plot */
2214 
2215  return SUCCESS;
2216 
2217 } /* ksepi_predownload_plot() */
KS_SEQ_CONTROL seqctrl
Definition: kssat.e:53
void ksscan_plotloop_shots(const KSSCAN_LOOP_CONTROL *loop_control, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
Executes a single-slice single-pass scan loop used for plotting all shots states
Definition: ksscan.cc:537
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:114
KS_SELRF selrfexc
Definition: ksepi_implementation.e:95
KSDIFF_CONTROL ksepi_diffctrl
Definition: ksepi_implementation.e:299
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
KS_EPI dynreftrain
Definition: ksepi_implementation.e:93
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:302
void ks_plot_host_seqctrl(const KS_SEQ_CONTROL *ctrl, const KS_PHASEENCODING_PLAN *plan)
ADDTITLEHERE
Definition: KSFoundation_host.c:7596
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:6860
void ksdiff_plotloop(const KSDIFF_CONTROL *diff_control, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), const SCAN_INFO *scan_info)
Executes a loop over all diffusion direction for plotting purposes
Definition: ksdiffusion.cc:502
s64 ksdiff_schemeloop(const KSDIFF_CONTROL *diff_control, const KSSCAN_LOOP_CONTROL *orig_loop_control, KS_DYNAMIC_STATE *dynamic, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
Executes all loops for a diffusion scheme according to the provided loop control
Definition: ksdiffusion.cc:428
KS_EPI epitrain
Definition: ksepi_implementation.e:92
char ks_psdname[256]
Definition: GERequired.e:245
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:91
void ks_plot_slicetime_begin()
ADDTITLEHERE
Definition: KSFoundation_common.c:4266
KS_SELRF selrfref
Definition: ksepi_implementation.e:96
KSSAT_MODULE kssat
Definition: kssat.e:112
void ks_plot_slicetime_end()
ADDTITLEHERE
Definition: KSFoundation_common.c:4316
void ks_print_trap(KS_TRAP trap, FILE *fp)
Writes out the contents of a KS_TRAP sequence object for debugging
Definition: KSFoundation_host.c:6780
STATUS STATUS STATUS existfile(const char *fname)
ADDTITLEHERE
Definition: KSFoundation_common.c:203
KS_TRAP spoiler
Definition: ksepi_implementation.e:94
KSSCAN_LOOP_CONTROL ksepi_fleet_loopctrl
Definition: ksepi_implementation.e:303
s64 ksepi_scan_scanloop()
Plays out all volumes and passes of a single or multi-pass scan
Definition: ksepi_implementation.e:3180
void ks_plot_psd(const KS_SEQ_CONTROL *ctrl, const KSSCAN_LOOP_CONTROL *loopctrl)
Wrapper function for plotting a module/sequence entry
Definition: ksscan.cc:440
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:82
void ks_eval_seqcollection_resetninst(KS_SEQ_COLLECTION *seqcollection)
Set the .nseqinstances field of each sequence module (KS_SEQ_CONTROL) equal to 0
Definition: KSFoundation_host.c:5929
KS_CORESLICETIME ksepi_scan_coreslicegroup(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Function to run for scan to execute one slice of the ksepi sequence module with optional sat module...
Definition: ksepi_implementation.e:3081
const KSSCAN_LOOP_CONTROL * ksepi_get_loop_ctrl()
Function to automatically switch between inverision and standard loop control
Definition: ksepi_implementation.e:2300
KS_TRAP diffgrads[3]
Definition: ksepi_implementation.e:97
void ks_print_selrf(KS_SELRF selrf, FILE *fp)
Writes out the contents of a KS_SELRF sequence object for debugging
Definition: KSFoundation_host.c:6945
KS_CORESLICETIME ksepi_scan_fleet_coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Plays out one slice for the ksepi_fleetseq sequence module in real time during scanning
Definition: ksepi_implementation.e:3114

◆ 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. This function is called last in predownload()

The rhuser variables here are needed for the Matlab recon recon_ksepi2.m to work, so they should not be changed. Setting rhileaves here to 1, also for multi-shot EPI, is critical to make Nyquist ghost correction work in recon for multi-shot EPI.

The rhrecon is set to 961 to call /usr/g/bin/recon961 on the scanner, which is present when this PSD is bundled with a compiled version of the matlab recon has been installed from an RPM. rhrecon may be changed to any other number to call another recon script, possibly one that just copies the scan archive off the scanner, or compiled variants of the recon_ksepi2.m script for VRE recons.

Return values
STATUSSUCCESS or FAILURE
2241  {
2242 
2243  /* These rhusers are read by epi2/recon_ksepi2.m
2244  epi/recon_epi.m cannot reconstruct this PSD */
2245 
2246  rhuser23 = (ksepi_reflines > 0) ? (float) (ksepi.dynreftrain.read.acq.pos[0] - ksepi.seqctrl.momentstart) : 0.0;
2247  rhuser25 = (ksepi_reflines > 0) ? (float) (ksepi.epitrain.read.acq.pos[0] - ksepi.seqctrl.momentstart - ksepi.pre_delay.pg_duration) : 0.0;
2248 
2249 
2250  /* FLEET */
2251  rhuser28 = (float) ksepi_fleetseq.epitrain.read.res; /* store num kx lines for FLEET */
2252  rhuser36 = (float) (ksepi_fleetseq.epitrain.read.grad.plateautime / 2) / 1.0e6; /* halfplateau time for FLEET [s] */
2253  rhuser37 = (float) (ksepi_fleetseq.epitrain.read.grad.ramptime)/ 1.0e6; /* attack/decay time for FLEET [s] */
2254  rhuser39 = (float) ksepi_fleetseq.epitrain.read.acq.filt.tsp; /* time between sample points [often 2us] */
2255 
2256  /* MAIN */
2257  rhuser31 = (float) ksepi.epitrain.R_ky; /* store for custom recon to know */
2258 
2259  /* GERequired.e uses: rhuser32-25 (VRGF) and rhuser48 (scantime) */
2260  rhuser45 = 1; /* flag for recon to indicate the existence of metadata.readpolarity (will be discontinued, and use .version instead) */;
2261 
2262  ihtr = optr;
2264 
2265  /* This is only important for the recon header, we don't zerofill the ref lines and set it to one */
2266  cvoverride(rhileaves, 1, PSD_FIX_ON, PSD_EXIST_ON);
2267 
2268  rhrecon = 961; /* VRE recon using Matlab recon (recon_epi.m). See matlab/deploy/rpmbuild on how to make an RPM */
2269 
2270  return SUCCESS;
2271 
2272 } /* ksepi_predownload_setrecon() */
int plateautime
Definition: KSFoundation.h:672
int R_ky
Definition: KSFoundation.h:1940
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
KS_EPI dynreftrain
Definition: ksepi_implementation.e:93
int momentstart
Definition: KSFoundation.h:1228
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:302
int * pos
Definition: KSFoundation.h:844
KS_TRAP grad
Definition: KSFoundation.h:1561
KS_EPI epitrain
Definition: ksepi_implementation.e:92
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:91
int res
Definition: KSFoundation.h:1552
void GEReq_predownload_setrecon_annotations_epi(KS_EPI *epi, int echogap)
Sets ih*** variables for TE and rBW annotation based on a KS_EPI
Definition: GERequired.e:2903
KS_READTRAP read
Definition: KSFoundation.h:1932
int pg_duration
Definition: KSFoundation.h:545
FILTER_INFO filt
Definition: KSFoundation.h:843
int ksepi_reflines
Definition: ksepi_implementation.e:261
KS_READ acq
Definition: KSFoundation.h:1549
KS_WAIT pre_delay
Definition: ksepi_implementation.e:98
int ramptime
Definition: KSFoundation.h:671
KS_EPI epitrain
Definition: ksepi_implementation.e:115

◆ ksepi_pg_fleet()

STATUS ksepi_pg_fleet ( int  start_time)

The FLEET pulse sequence generation

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). The FLEET sequence module is needed for GRAPPA calibration in the recon (recon_ksepi2.m) for 2D scans

Return values
STATUSSUCCESS or FAILURE
2519  {
2520 
2521  STATUS status;
2522  KS_SEQLOC tmploc = KS_INIT_SEQLOC;
2523 
2524  if (ksepi_fleet == FALSE) {
2525  return SUCCESS;
2526  }
2527 
2528  if (start_time < KS_RFSSP_PRETIME) {
2529  return KS_THROW("1st arg (pos start) must be at least %d us", KS_RFSSP_PRETIME);
2530  }
2531 
2532  /*******************************************************************************************************
2533  * RF Excitation
2534  *******************************************************************************************************/
2535  tmploc.ampscale = 1.0;
2536  tmploc.pos = RUP_GRD(start_time + KS_RFSSP_PRETIME);
2537  tmploc.board = ZGRAD;
2538 
2539  /* N.B.: ks_pg_selrf()->ks_pg_rf() detects that ksepi_fleetseq.selrfexc is an excitation pulse
2540  (ksepi_fleetseq.selrfexc.rf.role = KS_RF_ROLE_EXC) and will also set ksepi_fleetseq.seqctrl.momentstart
2541  to the absolute position in [us] of the isocenter of the RF excitation pulse */
2543  KS_RAISE(status);
2544 
2547 
2548  /*******************************************************************************************************
2549  * EPI echo time shifting
2550  *******************************************************************************************************/
2551  if (ksepi_echotime_shifting_fleet == TRUE) {
2552  tmploc.board = KS_ALL;
2554  KS_RAISE(status);
2555  tmploc.pos += GRAD_UPDATE_TIME;
2556  }
2557 
2558  /*******************************************************************************************************
2559  * EPI readout including de/rephasers on freq and phase encoding axes (net zero moment on both axes)
2560  *******************************************************************************************************/
2561 
2562  if (ksepi_slicecheck)
2563  tmploc.board = KS_FREQZ_PHASEY;
2564  else
2565  tmploc.board = KS_FREQX_PHASEY;
2566  tmploc.ampscale = ksepi_readsign;
2568  KS_RAISE(status);
2569  tmploc.pos += ksepi_fleetseq.epitrain.duration; /* end of EPI (incl. x/y rephasers, but not zphaser) */
2570 
2571  /*******************************************************************************************************
2572  * Gradient spoilers on Y and Z (at the same time)
2573  *******************************************************************************************************/
2574  tmploc.ampscale = 1.0;
2575 
2576  tmploc.board = YGRAD;
2578  KS_RAISE(status);
2579  tmploc.board = ZGRAD;
2581  KS_RAISE(status);
2582 
2583  tmploc.pos += ksepi_fleetseq.spoiler.duration;
2584 
2585  /*******************************************************************************************************
2586  * EPI echo time shifting
2587  *******************************************************************************************************/
2588  if (ksepi_echotime_shifting_fleet == TRUE) {
2589  tmploc.pos += GRAD_UPDATE_TIME;
2590  tmploc.board = KS_ALL;
2591  status = ks_pg_wait(&ksepi_fleetseq.post_delay, tmploc, &ksepi.seqctrl);
2592  KS_RAISE(status);
2593  tmploc.pos += IMax(2, psd_grd_wait, psd_rf_wait) + GRAD_UPDATE_TIME;
2595  }
2596 
2597  /*******************************************************************************************************
2598  * Set the minimal sequence duration (ksepi.seqctrl.min_duration) by calling
2599  * ks_eval_seqctrl_setminduration()
2600  *******************************************************************************************************/
2601 
2602  /* make sure we are divisible by GRAD_UPDATE_TIME (4us) */
2603  tmploc.pos = RUP_GRD(tmploc.pos);
2604 
2605 #ifdef HOST_TGT
2606  /* 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() */
2608  ks_eval_seqctrl_setminduration(&ksepi_fleetseq.seqctrl, tmploc.pos); /* tmploc.pos now corresponds to the end of last gradient in the sequence */
2609 #endif
2610 
2611  return SUCCESS;
2612 
2613 } /* ksepi_pg_fleet() */
int ksepi_readsign
Definition: ksepi_implementation.e:225
Definition: KSFoundation.h:2319
KS_TRAP grad
Definition: KSFoundation.h:1463
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:114
int pos
Definition: KSFoundation.h:463
KS_WAIT pre_delay
Definition: ksepi_implementation.e:118
int ksepi_eval_ssitime()
The SSI time for the sequence
Definition: ksepi_implementation.e:1965
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
STATUS ks_pg_selrf(KS_SELRF *selrf, KS_SEQLOC loc, KS_SEQ_CONTROL *ctrl) WARN_UNUSED_RESULT
Places a KS_SELRF sequence object on a gradient (and RF) board at some position in the pulse sequence...
Definition: KSFoundation_common.c:2817
int momentstart
Definition: KSFoundation.h:1228
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:302
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:2889
int board
Definition: KSFoundation.h:462
Definition: KSFoundation.h:2324
float ampscale
Definition: KSFoundation.h:464
Definition: KSFoundation.h:2326
int duration
Definition: KSFoundation.h:1943
#define KS_RFSSP_POSTTIME
Definition: KSFoundation.h:218
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:91
KS_RF rf
Definition: KSFoundation.h:1454
KS_TRAP spoiler
Definition: ksepi_implementation.e:116
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:3365
int ksepi_echotime_shifting_fleet
Definition: ksepi_implementation.e:251
int ksepi_echotime_shifting_sumdelay_fleet
Definition: ksepi_implementation.e:321
STATUS ks_pg_trap(KS_TRAP *trap, KS_SEQLOC loc, KS_SEQ_CONTROL *ctrl) WARN_UNUSED_RESULT
Places a KS_TRAP sequence object on a board at some position in the pulse sequence
Definition: KSFoundation_common.c:1802
#define KS_RAISE(status)
Definition: KSFoundation.h:190
typedef struct used as argument to ks_pg_*** functions to control where and when to place a sequence ...
Definition: KSFoundation.h:461
KS_WAIT post_delay
Definition: ksepi_implementation.e:119
KS_TRAP postgrad
Definition: KSFoundation.h:1464
int iso2end
Definition: KSFoundation.h:1033
int ssi_time
Definition: KSFoundation.h:1226
STATUS ks_eval_seqctrl_setminduration(KS_SEQ_CONTROL *seqctrl, int mindur)
Sets the minimum duration and duration fields of a KS_SEQ_CONTROL struct based on some minimum time (...
Definition: KSFoundation_host.c:4921
int psd_grd_wait
#define KS_INIT_SEQLOC
Definition: KSFoundation.h:287
int duration
Definition: KSFoundation.h:673
int ksepi_slicecheck
Definition: ksepi_implementation.e:197
int psd_rf_wait
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
int ksepi_fleet
Definition: ksepi_implementation.e:250
KS_SELRF selrfexc
Definition: ksepi_implementation.e:117
int ramptime
Definition: KSFoundation.h:671
KS_EPI epitrain
Definition: ksepi_implementation.e:115
#define KS_RFSSP_PRETIME
Definition: KSFoundation.h:217

◆ ksepi_fleet_scan_seqstate()

STATUS ksepi_fleet_scan_seqstate ( const SCAN_INFO *  slice_pos,
KS_PHASEENCODING_COORD  starting_coord,
ks_enum_epiblipsign  blipsign 
)

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

This function sets the current state of all FLEET sequence objects being part of KSEPI_FLEET_SEQUENCE, incl. gradient amplitude changes, RF freq/phases and receive freq/phase based on current slice position and phase encoding indices for a given sequence playout in ksepi_scan_fleet_coreslice() during scan.

Parameters
slice_posPointer to the SCAN_INFO structure containing slice information.
starting_coordThe starting coordinate for the scan.
blipsignThe blip sign for the scan.
Return values
STATUSSUCCESS or FAILURE
2701  {
2702  float exc_rfphase;
2703 
2704  /* RF frequency & phase */
2705  if (ksepi_rfspoiling) {
2708  } else {
2709  exc_rfphase = 0;
2710  }
2711 
2712  if (slice_pos != NULL) {
2713  ks_scan_rotate(*slice_pos);
2715  ks_scan_selrf_setfreqphase(&ksepi_fleetseq.selrfexc, 0, *slice_pos, exc_rfphase);
2716 
2717  /* Echo time shifting */
2719  int pre_delay = ksepi_fleetseq.pre_delay.pg_duration;
2720  int post_delay = ksepi_fleetseq.post_delay.pg_duration;
2721  int kyshot = starting_coord.ky % ksepi_fleetseq.epitrain.blipphaser.R;
2723  float delta_t = (float) epiesp / (float) ksepi_fleetseq.epitrain.blipphaser.R;
2724 
2725  if (kyshot >= 0) {
2726  if (blipsign == KS_EPI_POSBLIPS) {
2727  pre_delay = RUP_GRD((int) (delta_t * (ksepi_fleetseq.epitrain.blipphaser.R-1-kyshot)));
2728  } else if (blipsign == KS_EPI_NEGBLIPS) {
2729  pre_delay = RUP_GRD((int) (delta_t * kyshot));
2730  }
2731  }
2732  ks_scan_wait(&ksepi_fleetseq.pre_delay, pre_delay);
2733  post_delay = ksepi_echotime_shifting_sumdelay_fleet - pre_delay;
2734  ks_scan_wait(&ksepi_fleetseq.post_delay, post_delay);
2735  } /* echotime shifting FLEET */
2736 
2737  ks_scan_epi_shotcontrol(&ksepi_fleetseq.epitrain, 0, *slice_pos, starting_coord, blipsign, exc_rfphase);
2738  } else {
2740  }
2741 
2742  return SUCCESS;
2743 
2744 } /* 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:566
void ks_scan_epi_shotcontrol(KS_EPI *epi, int echo, SCAN_INFO sliceinfo, KS_PHASEENCODING_COORD starting_coord, ks_enum_epiblipsign blipsign, float rcvphase)
Changes the gradient state of a KS_EPI object for the given slice information
Definition: KSFoundation_tgt.c:1405
float ks_scan_rf_phase_spoiling(int counter)
Returns spoiling phase for a given RF counter
Definition: KSFoundation_common.c:4827
int R
Definition: KSFoundation.h:1723
int ksepi_rfspoiling
Definition: ksepi_implementation.e:199
KS_WAIT pre_delay
Definition: ksepi_implementation.e:118
KS_PHASER blipphaser
Definition: KSFoundation.h:1937
KSEPI_FLEET_SEQUENCE ksepi_fleetseq
Definition: ksepi_implementation.e:302
s16 ky
Definition: KSFoundation.h:1750
KS_TRAP grad
Definition: KSFoundation.h:1561
void ks_scan_rf_off(KS_RF *rf, int instanceno)
Sets the amplitude of one or all instances of an RF pulse (KS_RF) to zero
Definition: KSFoundation_tgt.c:597
void ks_scan_selrf_setfreqphase(KS_SELRF *selrf, int instanceno, SCAN_INFO sliceinfo, float rfphase)
Updates the frequency and phase of one or all instances of a slice selective RF pulse (KS_SELRF)...
Definition: KSFoundation_tgt.c:683
KS_RF rf
Definition: KSFoundation.h:1454
KS_READTRAP read
Definition: KSFoundation.h:1932
int ksepi_echotime_shifting_fleet
Definition: ksepi_implementation.e:251
Definition: KSFoundation.h:2330
int ksepi_echotime_shifting_sumdelay_fleet
Definition: ksepi_implementation.e:321
KS_WAIT post_delay
Definition: ksepi_implementation.e:119
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:161
int pg_duration
Definition: KSFoundation.h:545
void ks_scan_rotate(SCAN_INFO slice_pos)
Performs a rotation of the logical system on hardware (WARP)
Definition: KSFoundation_tgt.c:1179
int read_spacing
Definition: KSFoundation.h:1942
int duration
Definition: KSFoundation.h:673
KS_SELRF selrfexc
Definition: ksepi_implementation.e:117
int rfspoiling_phase_counter
Definition: ksepi_implementation.e:3221
Definition: KSFoundation.h:2330
KS_EPI epitrain
Definition: ksepi_implementation.e:115

◆ ksepi_scan_rf_off()

void ksepi_scan_rf_off ( )

Sets all RF pulse amplitudes to zero

Returns
void
2755  {
2756  ks_scan_rf_off(&ksepi.selrfexc.rf, INSTRALL);
2757  ks_scan_rf_off(&ksepi.selrfref.rf, INSTRALL);
2758 
2759 } /* ksepi_scan_rf_off() */
KS_SELRF selrfexc
Definition: ksepi_implementation.e:95
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
void ks_scan_rf_off(KS_RF *rf, int instanceno)
Sets the amplitude of one or all instances of an RF pulse (KS_RF) to zero
Definition: KSFoundation_tgt.c:597
KS_RF rf
Definition: KSFoundation.h:1454
KS_SELRF selrfref
Definition: ksepi_implementation.e:96

◆ ksepi_scan_attach_metadata() [2/2]

void ksepi_scan_attach_metadata ( KS_EPI epitrain,
KS_EPI dynreftrain,
const KS_DYNAMIC_STATE *  dynamic,
uint8_t  sequence_group 
)

Copy selected elements in KS_DYNAMIC_STATE to KSEPI_METADATA for data tagging for recon

The elements in KS_DYNAMIC_STATE are set by the nested scan loop functions (for EPI that is in ksepi.cc). These elements are e.g. .average, .shot, .slloc. For more details see KS_DYNAMIC_STATE.

With a 22-byte size limit of additional data to each DAB packet (i.e. each readout lobe), the 22-byte KSEPI_METADATA struct will here be filled with selected information from the dynamic struct (which is too large to be passed on as DAB packets) as well as with static data (sequence_group). The selected content of information in KSEPI_METADATA is given in ksepi2.h, where for now some free fields are available for future use.

To reduce the byte usage, diff_ampX/Y/Z are converted from float to int16 and scaled by 32767.

Once the local KSEPI_METADATA metadata_out has been filled, it is passed to ks_loaddab() in this function.

Note that the sequence-independent KS_DYNAMIC_STATE can grow in the future with new fields to support more needs for various PSDs. In contrast, care needs to be taken not only to limit the number of bytes used in KSEPI_METADATA, and also to not shuffle the fields of KSEPI_METADATA for backwards compatibility of the Matlab recon ksepi2_recon.m, which uses dab_getinfo_ksepi2.m to parse each raw frame's additional bytes where the KSEPI_METADATA is stored.

Parameters
[in]epitrainPointer to KS_EPI for the main EPI train
[in]dynreftrainPointer to KS_EPI for the dynamic ref lines (may be NULL)
[in]dynamicPointer to KS_DYNAMIC_STATE that stores nex, slice, shot, vol information
[in]sequence_groupOne of enums in KSEPI_SEQINDICES
Returns
void
2883  {
2884  float readamp;
2885  int i;
2886 
2888 
2889  metadata.sequence_group = sequence_group; /* enum KSEPI_SEQINDICES */
2890 
2891  metadata.average = (int8_t) dynamic->average; /* NEX */
2892  metadata.slloc = (int16_t) dynamic->slloc;
2893  metadata.shot = (int16_t) dynamic->shot;
2894  metadata.vol_rep = (int16_t) dynamic->vol;
2895 
2896  if (opdiffuse) {
2897  float logicalmax = FMax(3, loggrd.tx, loggrd.ty, loggrd.tz);
2898  metadata.diff_ampX = (int16_t) (dynamic->diff_amp[XGRAD] * loggrd.tx / logicalmax * MAX_PG_IAMP);
2899  metadata.diff_ampY = (int16_t) (dynamic->diff_amp[YGRAD] * loggrd.ty / logicalmax * MAX_PG_IAMP);
2900  metadata.diff_ampZ = (int16_t) (dynamic->diff_amp[ZGRAD] * loggrd.tz / logicalmax * MAX_PG_IAMP);
2901  } else {
2902  metadata.diff_ampX = (int16_t) 0;
2903  metadata.diff_ampY = (int16_t) 0;
2904  metadata.diff_ampZ = (int16_t) 0;
2905  }
2906  metadata.inner_shot = (int8_t) dynamic->inner_shot;
2907 
2908  /* Main EPI train(s) (KS_EPI) */
2909  for (i = 0; i < ks_numplaced(&epitrain->read.acq.base); i++) {
2910  readamp = ks_get_trapamp_instance(&epitrain->read.grad, i);
2911  metadata.readpolarity = (int8_t) areSame(readamp,0.0) ? 0 : ((readamp > 0.0) ? 1 : -1);
2912  metadata.seqpart = KSEPI_SEQPART_EPITRAIN; /* enum KSEPI_SEQPARTS */
2913  if (ksepi_metadump) { ksepi_dump_metadata(&metadata, dynamic); }
2914  ks_loaddab(&epitrain->read.acq.echo[i], (char *) &metadata);
2915  }
2916 
2917  /* Dynamic ref lines (KS_EPI). ksepi_scan_coreslice_prep()->ks_scan_epi_loadecho(&seq->dynreftrain.... view # = -1 */
2918  if (dynreftrain != NULL) {
2919  for (i = 0; i < ks_numplaced(&dynreftrain->read.acq.base); i++) {
2920  readamp = ks_get_trapamp_instance(&dynreftrain->read.grad, i);
2921  metadata.readpolarity = (int8_t) areSame(readamp,0.0) ? 0 : ((readamp > 0.0) ? 1 : -1);
2922  metadata.seqpart = KSEPI_SEQPART_DYNREFTRAIN; /* enum KSEPI_SEQPARTS */
2923  if (ksepi_metadump) { ksepi_dump_metadata(&metadata, dynamic); }
2924  ks_loaddab(&dynreftrain->read.acq.echo[i], (char *) &metadata);
2925  }
2926  }
2927 
2928 } /* ksepi_scan_attach_metadata() */
int16_t diff_ampZ
Definition: ksepi_implementation.e:169
int8_t average
Definition: ksepi_implementation.e:162
WF_PULSE * echo
Definition: KSFoundation.h:846
#define areSame(a, b)
Definition: KSFoundation.h:144
Definition: ksepi_implementation.e:126
int16_t vol_rep
Definition: ksepi_implementation.e:166
int8_t readpolarity
Definition: ksepi_implementation.e:171
KS_TRAP grad
Definition: KSFoundation.h:1561
KS_BASE base
Definition: KSFoundation.h:839
LOG_GRAD loggrd
uint8_t seqpart
Definition: ksepi_implementation.e:172
void ksepi_dump_metadata(KSEPI_METADATA *metadata, const KS_DYNAMIC_STATE *dynamic)
Write out a textfile of the metadata created in ksepi_scan_attach_metadata() (WTools only)...
Definition: ksepi_implementation.e:2775
KS_READTRAP read
Definition: KSFoundation.h:1932
#define KSEPI_INIT_METADATA
Definition: ksepi_implementation.e:179
int ks_numplaced(KS_BASE *base)
ADDTITLEHERE
Definition: KSFoundation_common.c:4838
KSEPI specific datastore struct for recon (c.f. ksepi_scan_attach_metadata())
Definition: ksepi_implementation.e:158
Definition: ksepi_implementation.e:126
int8_t inner_shot
Definition: ksepi_implementation.e:170
int16_t diff_ampX
Definition: ksepi_implementation.e:167
int16_t shot
Definition: ksepi_implementation.e:165
uint8_t sequence_group
Definition: ksepi_implementation.e:161
void ks_loaddab(WF_PULSE_ADDR echo, const char *dab_array)
ADDTITLEHERE
Definition: KSFoundation_tgt.c:1504
KS_READ acq
Definition: KSFoundation.h:1549
int ksepi_metadump
Definition: ksepi_implementation.e:280
int16_t slloc
Definition: ksepi_implementation.e:164
int16_t diff_ampY
Definition: ksepi_implementation.e:168
float ks_get_trapamp_instance(const KS_TRAP *trap, int instance)
Get the amplitude in G/cm for an instance of a KS_TRAP (excluding realtime changes)
Definition: KSFoundation_common.c:4862

◆ 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
3239  {
3240 
3241  GEReq_initRSP();
3242 
3243  /* Here goes code common for APS2, MPS2 and SCAN */
3244 
3245  ks_scan_switch_to_sequence(&ksepi.seqctrl); /* switch to main sequence */
3246  scopeon(&seqcore); /* Activate scope for core */
3247  syncon(&seqcore); /* Activate sync for core */
3248  setssitime(ksepi.seqctrl.ssi_time / HW_GRAD_UPDATE_TIME);
3249 
3250  /* can we make these independent on global rsptrigger and rsprot in orderslice? */
3251  settriggerarray( (short) ksepi_get_loop_ctrl()->slicetiming.slice_plan.nslices_per_pass, rsptrigger);
3252 
3254 
3255  return SUCCESS;
3256 
3257 } /* ksepi_scan_init() */
void ks_scan_switch_to_sequence(KS_SEQ_CONTROL *ctrl)
Definition: KSFoundation_tgt.c:1625
STATUS setssitime(long)
KSEPI_SEQUENCE ksepi
Definition: ksepi_implementation.e:297
void GEReq_initRSP(void)
RSP Init. To be inserted in the psdinit() function (or scan()) in the main sequence
Definition: GERequired.e:3773
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:91
int ssi_time
Definition: KSFoundation.h:1226
const KSSCAN_LOOP_CONTROL * ksepi_get_loop_ctrl()
Function to automatically switch between inverision and standard loop control
Definition: ksepi_implementation.e:2300
int rfspoiling_phase_counter
Definition: ksepi_implementation.e:3221

◆ 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
3267  {
3268 
3269  if (!ANYINVERSION) {
3271  } else {
3273  }
3274 
3275  return SUCCESS;
3276 
3277 } /* ksepi_scan_prescanloop() */
void ksscan_prescanloop(const KSSCAN_LOOP_CONTROL *loop_control, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), int nloops, int dda)
Prescan loop called from both APS2 and MPS2 entry points
Definition: ksscan.cc:603
void ksinv_prescanloop(KSINV_LOOP_CONTROL *inv_loopctrl, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), KS_CORESLICETIME irslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), int nloops, int dda)
Prescan loop called from both APS2 and MPS2 entry points
Definition: ksinversion.cc:1285
KSINV_LOOP_CONTROL ksepi_inv_loopctrl
Definition: ksepi_implementation.e:307
KS_CORESLICETIME ksepi_scan_irslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Wrapper function to ksinv_scan_irslice() with ksepi_inv (global in this file) as argument
Definition: ksepi_implementation.e:2942
KSSCAN_LOOP_CONTROL ksepi_loopctrl
Definition: ksepi_implementation.e:298
KS_CORESLICETIME ksepi_scan_coreslicegroup(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic)
Function to run for scan to execute one slice of the ksepi sequence module with optional sat module...
Definition: ksepi_implementation.e:3081
#define ANYINVERSION
Definition: KSFoundation.h:346

◆ ksepi_diffusion_init_UI()

STATUS ksepi_diffusion_init_UI ( )

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

Return values
STATUSSUCCESS or FAILURE
92  {
93  int i;
94 
95  if (opdiffuse != KS_EPI_DIFFUSION_ON) {
96  return SUCCESS;
97  }
98 
99 
100  pidiffproctype = 0;/* Bitmask to show/hide automated DTI processing buttons */
101 
102  /* Optimize TE / super G check box */
103 #if EPIC_RELEASE >= 27
104  pimintediflabel = HAVE_PREMIER_GRADIENTS; /* Label indicator: 0 - Optimize TE, 1 - Super G */
105  pimintedifvis = HAVE_PREMIER_GRADIENTS; /* Visibility of the "Optimize TE"/"Super G" button : 0 - invisible, 1 - visible */
106 #endif
107  pimintedifnub = HAVE_PREMIER_GRADIENTS; /* Optimize TE button control in diffusion screen */
108  pimintedifdef = 0; /* Default Optimize TE button control */
109  cvset(opmintedif,0,1,0,""); /* Optimize TE button control */
110 
111  pinumsynbnub = 0; /* No synthetic b-values */
112  pisynbvalstab = 0;
113  piseparatesynbnub = 0;
114  pidifrecnub = 0;
115  pidifaxnub = 1;
116  pidualspinechonub = 0; /* doesn't help, still checked when TENSOR is chosen */
117 
118  /* number of b-values */
119  cvset(opnumbvals, 1, KSEPI_DIFFUSION_MAXBVALS, 1, "");
120  pinumbnub = 63;
121  pinumbval2 = 1;
122  pinumbval3 = 2;
123  pinumbval4 = 3;
124  pinumbval5 = 4;
125  pinumbval6 = KSEPI_DIFFUSION_MAXBVALS;
126 
127  /* b-value table */
128  cvset(opbval, 0, KSEPI_DIFFUSION_MAXBVALUE, 1000, "");
129  pibvalstab = 1; /* show bvalue table */
130  avminbvalstab = 10.0;
131  avmaxbvalstab = KSEPI_DIFFUSION_MAXBVALUE;
132  if (existcv(opnumbvals) == FALSE) {
133  /* until number of b-value has been selected, set up a range of b-values */
134  for (i = 0; i < 10; i++)
135  bvalstab[i] = 1000 + 500 * i;
136  }
137 
138  pidifnextab = 1; /* Allow NEX input in table (and hide normal NEX) */
139  avmindifnextab = 1;
140  avmaxdifnextab = 10;
141 
142  /* Number of T2 menu (opdifnumt2) - DISABLED BY DEFAULT
143  - produces this many .nb0 and .nb0neg volumes in recon (increases total # of DICOM images) */
144  pidifnumt2defval = 1;
145  cvdef(opdifnumt2, pidifnumt2defval);
146  opdifnumt2 = pidifnumt2defval;
147  pidifnumt2nub = 0; /* Disable menu (use opdifnext2 for higher b0 SNR). Possible though to enable menu, recon will produce this many separate b0 vols */
148  pidifnumt2val2 = 1;
149 
150  /* NEX for T2 (opdifnext2)
151  - produces this many averages of .nb0 and .nb0neg volumes in recon without increasing the total # of DICOM images */
152  cvset(opdifnext2, 1, 20, 1, "");
153  pidifnext2nub = 63;
154  pidifnext2val2 = 1;
155  pidifnext2val3 = 2;
156  pidifnext2val4 = 3;
157  pidifnext2val5 = 4;
158  pidifnext2val6 = 5;
159 
160  /* Number of diffusion directions menu (opdifnumdirs) */
161  pidifnumdirsdefval = 6;
162  cvset(opdifnumdirs, 1, MAX_DIFFSCHEME_LENGTH, pidifnumdirsdefval, "");
163  pidifnumdirsnub = 15;
164  pidifnumdirsval2 = 6;
165  pidifnumdirsval3 = 15;
166  pidifnumdirsval4 = 25;
167 
168 
169  /* Max diffusion amplitude to work with [G/cm] (based on trial and error) */
171  if (opmintedif) {
172  /* 70 mT/m with longer TR */
173  _ksepi_diffusion_amp_scale.defval = 1.0;
174  } else {
175  /* without increasing min TR for b < 1500, max diff amp seems to be ~50 mT/m (~70%) */
176  _ksepi_diffusion_amp_scale.defval = 0.70;
177  }
178  } else {
179  /* by default, use 85% of physical max to allow for angled slices */
180  _ksepi_diffusion_amp_scale.defval = 0.85;
181  }
182  ksepi_diffusion_amp_scale = _ksepi_diffusion_amp_scale.defval;
183 
184  return SUCCESS;
185 
186 } /* ksepi_diffusion_init_UI() */
#define KSEPI_DIFFUSION_MAXBVALS
Definition: ksepi_implementation_diffusion.e:38
#define MAX_DIFFSCHEME_LENGTH
Definition: ksepi_implementation_diffusion.e:37
#define HAVE_PREMIER_GRADIENTS
Definition: KSFoundation.h:232
Definition: KSFoundation.h:2332
#define cvset(cv, min, max, def, desc)
Definition: KSFoundation.h:2380
#define KSEPI_DIFFUSION_MAXBVALUE
Definition: ksepi_implementation_diffusion.e:39
float ksepi_diffusion_amp_scale
Definition: ksepi_implementation_diffusion.e:53

◆ SolveCubic()

void SolveCubic ( double  a,
double  b,
double  c,
double  d,
int *  nsol,
double *  x 
)

Solve a third degree polynomial equation

Returns
void
202 {
203  double a1 = b/a, a2 = c/a, a3 = d/a;
204  double Q = (a1*a1 - 3.0*a2)/9.0;
205  double R = (2.0*a1*a1*a1 - 9.0*a1*a2 + 27.0*a3)/54.0;
206  double R2_Q3 = R*R - Q*Q*Q;
207  double theta;
208 
209  if (R2_Q3 <= 0){
210  *nsol = 3;
211  theta = acos(R/sqrt(Q*Q*Q));
212  x[0] = -2.0 * sqrt(Q) * cos( theta/3.0) - a1/3.0;
213  x[1] = -2.0 * sqrt(Q) * cos( (theta+2.0*PI)/3.0) - a1/3.0;
214  x[2] = -2.0 * sqrt(Q) * cos( (theta+4.0*PI)/3.0) - a1/3.0;
215  } else {
216  *nsol = 1;
217  x[0] = pow( sqrt(R2_Q3) + fabs(R), 1/3.0);
218  x[0] += Q/x[0];
219  x[0] *= (R < 0.0) ? 1 : -1;
220  x[0] -= a1/3.0;
221  }
222 
223 } /* SolveCubic() */

◆ ksepi_diffusion_calcTE()

STATUS ksepi_diffusion_calcTE ( double *  TE_s,
int  exciso2end,
int  crsh1_half180,
int  half180_crsh2,
int  readout2echo,
int  ramptime,
float  G,
int  bval_desired 
)

Calculate TE that will yield the desired b-value

Using a set of fixed times in the sequence as input arguments as well as the diffusion gradient amplitude and the desired b-value, this function calculates the echo time (TE) that will yield the desired b-value.

Parameters
[out]TE_sTE [s] that will yield the correct b-value
[in]exciso2end[us] RF excitation isocenter to end of exc rephaser
[in]crsh1_half180[us] left crusher start to RF isocenter of 1st/only 180
[in]half180_crsh2[us] RF isocenter to end of right crusher of 1st/only 180
[in]readout2echo[us] time from readout to echo
[in]ramptime[us] minimum ramp time
[in]G[G/cm] diffusion gradient amplitude
[in]bval_desired[s/mm^2] desired b-value
Return values
STATUSSUCCESS or FAILURE
245  {
246  double exciso2end_s = 1.0E-6 * RUP_GRD(exciso2end); /* [s] */
247  double crsh1_half180_s = 1.0E-6 * RUP_GRD(crsh1_half180); /* [s] */
248  double half180_crsh2_s = 1.0E-6 * RUP_GRD(half180_crsh2); /* [s] */
249  double readout2echo_s = 1.0E-6 * RUP_GRD(readout2echo); /* [s] */
250  double ramptime_s = 1.0E-6 * RUP_GRD(ramptime); /* [s] */
251  double fixedtime_s;
252  double gam_SI = (2 * PI * 42.58E6); /* [rad/(sT)] */
253  double G_SI = G / 100.0; /* [G/cm] -> [T/m] */
254  double sol[3];
255  int nsol;
256  double c0, c1, c2, c3, c0new;
257 
258  /* all double variables are in SI units (see genbvalcode.m for details on c0-c3 below) */
259 
260  fixedtime_s = FMax(2, exciso2end_s + crsh1_half180_s, half180_crsh2_s + readout2echo_s) + 2.0 * ramptime_s;
261 
262  c3 = 1.0 / 12.0;
263 
264  c2 = -(exciso2end_s + fixedtime_s - half180_crsh2_s - ramptime_s) / 4.0;
265 
266  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;
267 
268  c0 = (fixedtime_s * fixedtime_s) * half180_crsh2_s - exciso2end_s * (fixedtime_s * fixedtime_s) - exciso2end_s * (ramptime_s * ramptime_s) +
269  (7 * fixedtime_s * (ramptime_s * ramptime_s)) / 6 - (fixedtime_s * fixedtime_s) * ramptime_s + half180_crsh2_s * (ramptime_s * ramptime_s) +
270  (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;
271 
272  /* 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)
273  where
274  double gam_SI = (2 * PI * 42.58E6); [rad/(sT)]
275  double G_SI = G [G/cm] / 100.0; [T/m]
276 
277  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]
278  desired b-value: bval_desired; [s/mm^2]
279  F(TE_s) = b(TE_s) - bval_desired
280  Find TE_s that gives F(TE_s) = 0 => TE_s that will yield the correct b-value
281  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
282  =>
283  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)))
284  => [divide leading factors and make a new c0new = c0 - bval_desired/(1.0E-6 * gam_SI * gam_SI * G_SI * G_SI)
285  Fnew(TE_s) = c3 * pow(TE_s, 3.0) + c2 * pow(TE_s, 2.0) + c1 * TE_s + c0new
286  Put in c3, c2, c1, c0new into SolveCubic function to get TE_s where F(TE_s) = 0
287  */
288  c0new = c0 - (double) bval_desired / (1.0E-6 * gam_SI * gam_SI * G_SI * G_SI);
289 
290  /* Solve cubic function in TE */
291  SolveCubic(c3, c2, c1, c0new, &nsol, sol);
292 
293  if (nsol == 3)
294  *TE_s = FMax(3, sol[0], sol[1], sol[2]);
295  else
296  *TE_s = sol[0];
297 
298 
299  return SUCCESS;
300 
301 } /* ksepi_diffusion_calcTE() */
void SolveCubic(double a, double b, double c, double d, int *nsol, double *x)
Solve a third degree polynomial equation
Definition: ksepi_implementation_diffusion.e:196

◆ ksepi_diffusion_eval_gradients_TE()

STATUS ksepi_diffusion_eval_gradients_TE ( KSEPI_SEQUENCE epi,
const KSDIFF_CONTROL diff_ctrl 
)

Evaluate the diffusion gradients and TE

This function evaluates the diffusion gradients and TE based on the KSDIFF_CONTROL struct diff_ctrl and the KSEPI_SEQUENCE struct epi.

Parameters
[in,out]epiKSEPI_SEQUENCE struct
[in]diff_ctrlKSDIFF_CONTROL struct, with used fields .max_magnitude_amp and .bvalue
Return values
STATUSSUCCESS or FAILURE
317  {
318 
319  STATUS status;
320  int exciso2end = epi->selrfexc.rf.iso2end + KS_RFSSP_POSTTIME + epi->selrfexc.grad.ramptime + epi->selrfexc.postgrad.duration; /* RF excitation isocenter to end of exc rephaser [us] */
321  const int crsh1_half180 = KS_RFSSP_PRETIME + epi->selrfref.grad2rf_start + epi->selrfref.rf.start2iso; /* left crusher start to RF isocenter of 1st/only 180 [us] */
322  const int half180_crsh2 = epi->selrfref.rf.iso2end + epi->selrfref.rf2grad_end + KS_RFSSP_POSTTIME; /* RF isocenter to end of right crusher of 1st/only 180 [us] */
323  int i;
324 
325  if (ksepi_reflines > 0) {
326  exciso2end += epi->dynreftrain.duration;
327  if (ksepi_slicecheck == FALSE) { /* reflines dephaser may overlap with selrf rephaser unless slicecheck mode */
328  exciso2end -= IMin(2, epi->dynreftrain.readphaser.duration, epi->selrfexc.postgrad.duration);
329  }
330  }
331 
332  if (opdiffuse != KS_EPI_DIFFUSION_ON) {
333  return SUCCESS;
334  }
335 
336  /* Diffusion amplitude scaling to start out with. May decrease if b-value very small */
337  float amp_scale = ksepi_diffusion_amp_scale;
338  int plateautime = 0;
339 
340  const int ramptime = RUP_GRD(IMax(2, ks_syslimits_ramptimemax(loggrd), ksepi_diffusion_minramptime));
341  const int fixedtime = RUP_GRD(IMax(2, exciso2end + crsh1_half180, half180_crsh2 + epi->pre_delay.pg_duration + epi->epitrain.time2center) + 2 * ramptime);
342 
343  int bvalue_validated = FALSE;
344  const int max_attempts = 30;
345 
346  for (i=0; i < max_attempts; ++i) {
347 
348  double TE_s;
349  status = ksepi_diffusion_calcTE(&TE_s, exciso2end /* [us] */, crsh1_half180 /* [us] */, half180_crsh2 /* [us] */,
350  epi->epitrain.time2center /* [us] */,
351  ramptime /* [us] */,
352  amp_scale * diff_ctrl->max_magnitude_amp /* [G/cm] */,
353  diff_ctrl->bvalue /* [s/mm^2] */);
354  KS_RAISE(status);
355 
356  /* Save the TE found to the CV for later verification. ksepi_diffusion_echotime in [us] */
357  cvoverride(ksepi_diffusion_echotime, (TE_s * 1E6), PSD_FIX_OFF, PSD_EXIST_OFF);
359 
360  /* Set diffusion plateau times based on found TE */
361  plateautime = RDN_GRD(ksepi_diffusion_echotime / 2 - fixedtime);
362 
363  if (plateautime >= (2 * GRAD_UPDATE_TIME)) {
364  bvalue_validated = TRUE;
365  break;
366  }
367 
368  /* Too low b-value or long ramptimes leading to negative plateau times?
369  Reduce diffusion gradient amplitude and try again */
370  amp_scale *= 0.95;
371  }
372 
373  if (bvalue_validated == FALSE) {
374  return KS_THROW("TE => negative diffusion gradient plateau time");
375  }
376 
377  const char boards[] = "XYZ";
378  const float diffgrad_amps[] = {loggrd.tx, loggrd.ty, loggrd.tz};
379  for (i=0; i<3; ++i) {
380  ks_init_trap(&epi->diffgrads[i]);
381 
382  /* Build up the trap object(s) manually, now that we know the plateau time(s) */
383  epi->diffgrads[i].amp = diffgrad_amps[i] * amp_scale; /* [G/cm] */
384  epi->diffgrads[i].ramptime = ramptime;
385  epi->diffgrads[i].plateautime = plateautime;
386  sprintf(epi->diffgrads[i].description, "diffgrad_%c", boards[i]);
387 
388  /* duration and area are consequences of the fields just set (N.B. all are initialized to zero by ks_init_trap()) */
389  epi->diffgrads[i].duration = epi->diffgrads[i].plateautime + 2 * epi->diffgrads[i].ramptime;
390  epi->diffgrads[i].area = epi->diffgrads[i].amp * (float) (epi->diffgrads[i].plateautime + epi->diffgrads[i].ramptime);
391  }
392 
393  return SUCCESS;
394 
395 } /* ksepi_diffusion_eval_gradients_TE() */
int plateautime
Definition: KSFoundation.h:672
KS_TRAP grad
Definition: KSFoundation.h:1463
int ksepi_diffusion_echotime
Definition: ksepi_implementation_diffusion.e:58
int start2iso
Definition: KSFoundation.h:1032
KS_SELRF selrfexc
Definition: ksepi_implementation.e:95
float bvalue
Definition: ksdiffusion.h:46
int ksepi_diffusion_minramptime
Definition: ksepi_implementation_diffusion.e:60
KS_EPI dynreftrain
Definition: ksepi_implementation.e:93
KS_EPI epitrain
Definition: ksepi_implementation.e:92
int ks_syslimits_ramptimemax(LOG_GRAD loggrd)
Returns the minimum ramp time to get from zero to full gradient scale
Definition: KSFoundation_common.c:282
int duration
Definition: KSFoundation.h:1943
int grad2rf_start
Definition: KSFoundation.h:1466
#define KS_RFSSP_POSTTIME
Definition: KSFoundation.h:218
KS_RF rf
Definition: KSFoundation.h:1454
void ks_init_trap(KS_TRAP *trap)
Resets a KS_TRAP sequence object to its default value (KS_INIT_TRAP)
Definition: KSFoundation_host.c:62
KS_SELRF selrfref
Definition: ksepi_implementation.e:96
LOG_GRAD loggrd
Definition: KSFoundation.h:2332
STATUS ksepi_diffusion_calcTE(double *TE_s, int exciso2end, int crsh1_half180, int half180_crsh2, int readout2echo, int ramptime, float G, int bval_desired)
Calculate TE that will yield the desired b-value
Definition: ksepi_implementation_diffusion.e:245
float area
Definition: KSFoundation.h:670
#define KS_RAISE(status)
Definition: KSFoundation.h:190
float amp
Definition: KSFoundation.h:669
KS_TRAP postgrad
Definition: KSFoundation.h:1464
int iso2end
Definition: KSFoundation.h:1033
KS_DESCRIPTION description
Definition: KSFoundation.h:668
int pg_duration
Definition: KSFoundation.h:545
int time2center
Definition: KSFoundation.h:1944
float max_magnitude_amp
Definition: ksdiffusion.h:50
KS_TRAP readphaser
Definition: KSFoundation.h:1934
int ksepi_reflines
Definition: ksepi_implementation.e:261
int rf2grad_end
Definition: KSFoundation.h:1467
int duration
Definition: KSFoundation.h:673
int ksepi_slicecheck
Definition: ksepi_implementation.e:197
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
KS_TRAP diffgrads[3]
Definition: ksepi_implementation.e:97
float ksepi_diffusion_amp_scale
Definition: ksepi_implementation_diffusion.e:53
KS_WAIT pre_delay
Definition: ksepi_implementation.e:98
int ramptime
Definition: KSFoundation.h:671
#define KS_RFSSP_PRETIME
Definition: KSFoundation.h:217

◆ ksepi_eval_diffusion()

STATUS ksepi_eval_diffusion ( KSDIFF_CONTROL diff_ctrl)

Creation of KSDIFF_CONTROL using a KSDIFF_CONTROL_DESIGN struct set by this function

The KSDIFF_CONTROL_DESIGN struct is set up mostly by UI CVs on the Diffusion tab. This is then used by ksdiff_eval_design() to create the KSDIFF_CONTROL struct ksepi_diffctrl, which is later used in ksepi_eval_setupobjects()->ksepi_diffusion_eval_gradients_TE() to control diffusion timing, gradients, and TE

Note that all design structs are short-lived and are set up as a receipe for other structures to be used in pulsegen and scan

Parameters
[out]diff_ctrlKSDIFF_CONTROL struct to be created
Return values
STATUSSUCCESS or FAILURE
413  {
414 
415  STATUS status;
416 
418 
419  if (opdiffuse) {
420  /* diffusion design */
421  diff_design.nb0 = opdifnumt2;
422  diff_design.ndirs = opdifnumdirs;
423  diff_design.numbvals = opnumbvals;
424 
426 
427  diff_design.coordinate_system = (diff_design.ndirs == 4) ?
428  KSDIFF_PHYSICAL : /* tetrahedral case */
430 
431  int i = 0;
432  for (i = 0; i < diff_design.numbvals; i++) {
433  /* 'difnextab' & 'bvalstab' are global UI arrays for the Diffusion screen */
434  diff_design.bvalues[i] = bvalstab[i];
435  diff_design.multib_nex[i] = difnextab[i];
436  }
437  } /* diffusion */
438 
439  status = ksdiff_eval_design(&ksepi_diffctrl, &diff_design);
440  KS_RAISE(status);
441 
442  return SUCCESS;
443 
444 } /* ksepi_eval_diffusion() */
STATUS ksdiff_eval_design(KSDIFF_CONTROL *diff_control, const KSDIFF_CONTROL_DESIGN *design)
Generate a diffusion control from its design
Definition: ksdiffusion.cc:385
int ndirs
Definition: ksdiffusion.h:24
KSDIFF_CONTROL ksepi_diffctrl
Definition: ksepi_implementation.e:299
Definition: ksdiffusion.h:9
int nb0
Definition: ksdiffusion.h:23
#define HAVE_PREMIER_GRADIENTS
Definition: KSFoundation.h:232
Definition: ksdiffusion.h:11
Definition: ksdiffusion.h:11
int numbvals
Definition: ksdiffusion.h:28
#define KS_RAISE(status)
Definition: KSFoundation.h:190
Design of a control structure for performing diffusion weighting
Definition: ksdiffusion.h:22
ksdiff_physical_bound_type physical_bound_type
Definition: ksdiffusion.h:26
#define KSDIFF_INIT_CONTROL_DESIGN
Definition: ksdiffusion.h:33
float bvalues[KSDIFF_MAXBVALS]
Definition: ksdiffusion.h:29
Definition: ksdiffusion.h:9
int multib_nex[KSDIFF_MAXBVALS]
Definition: ksdiffusion.h:30
ksdiff_coordinate_system coordinate_system
Definition: ksdiffusion.h:25

◆ ksepi_diffusion_pg()

STATUS ksepi_diffusion_pg ( KSEPI_SEQUENCE epi,
int  TE 
)

Diffusion part of the ksepi_pg() function, placing diffusion gradients and the refocusing RF pulse in between

Return values
STATUSSUCCESS or FAILURE
458  {
459  KS_SEQLOC tmploc = KS_INIT_SEQLOC;
460  int i;
461  STATUS status;
462 
463  if (opdiffuse != KS_EPI_DIFFUSION_ON) {
464  return SUCCESS;
465  }
466 
467  /* First diffusion gradient right after the excitation and any reference lines */
468  tmploc.ampscale = 1.0;
470 
471  if (ksepi_slicecheck == FALSE) { /* reflines dephaser may overlap with selrf rephaser unless slicecheck mode */
472  tmploc.pos -= IMin(2, epi->dynreftrain.readphaser.duration, epi->selrfexc.postgrad.duration);
473  }
474 
475  if (ksepi_reflines > 0) {
476  tmploc.pos += epi->dynreftrain.duration;
477  }
478 
479  for (i = XGRAD; i <= ZGRAD; i++) {
480  tmploc.board = i;
481  status = ks_pg_trap(&epi->diffgrads[i], tmploc, &epi->seqctrl);
482  KS_RAISE(status);
483  }
484 
485  /* Selective RF Refocus with left (pregrad.) and right (postgrad.) crushers */
486  tmploc.pos = epi->seqctrl.momentstart + TE / 2 - (epi->selrfref.grad2rf_start + epi->selrfref.rf.start2iso);
487  status = ks_pg_selrf(&epi->selrfref, tmploc, &epi->seqctrl);
488  KS_RAISE(status);
489 
490  /* Second diffusion gradient after the refocusing pulse */
491  tmploc.ampscale = 1.0;
492  tmploc.pos += epi->selrfref.grad2rf_start + epi->selrfref.rf.start2iso + epi->selrfref.rf.iso2end + epi->selrfref.rf2grad_end;
493 
494  for (i = XGRAD; i <= ZGRAD; i++) {
495  tmploc.board = i;
496  status = ks_pg_trap(&epi->diffgrads[i], tmploc, &epi->seqctrl);
497  KS_RAISE(status);
498  }
499 
500  return SUCCESS;
501 
502 } /* ksepi_diffusion_pg() */
KS_TRAP grad
Definition: KSFoundation.h:1463
int start2iso
Definition: KSFoundation.h:1032
KS_SELRF selrfexc
Definition: ksepi_implementation.e:95
int pos
Definition: KSFoundation.h:463
KS_EPI dynreftrain
Definition: ksepi_implementation.e:93
STATUS ks_pg_selrf(KS_SELRF *selrf, KS_SEQLOC loc, KS_SEQ_CONTROL *ctrl) WARN_UNUSED_RESULT
Places a KS_SELRF sequence object on a gradient (and RF) board at some position in the pulse sequence...
Definition: KSFoundation_common.c:2817
int momentstart
Definition: KSFoundation.h:1228
int board
Definition: KSFoundation.h:462
float ampscale
Definition: KSFoundation.h:464
int duration
Definition: KSFoundation.h:1943
int grad2rf_start
Definition: KSFoundation.h:1466
KS_SEQ_CONTROL seqctrl
Definition: ksepi_implementation.e:91
KS_RF rf
Definition: KSFoundation.h:1454
KS_SELRF selrfref
Definition: ksepi_implementation.e:96
Definition: KSFoundation.h:2332
STATUS ks_pg_trap(KS_TRAP *trap, KS_SEQLOC loc, KS_SEQ_CONTROL *ctrl) WARN_UNUSED_RESULT
Places a KS_TRAP sequence object on a board at some position in the pulse sequence
Definition: KSFoundation_common.c:1802
#define KS_RAISE(status)
Definition: KSFoundation.h:190
typedef struct used as argument to ks_pg_*** functions to control where and when to place a sequence ...
Definition: KSFoundation.h:461
KS_TRAP postgrad
Definition: KSFoundation.h:1464
int iso2end
Definition: KSFoundation.h:1033
KS_TRAP readphaser
Definition: KSFoundation.h:1934
int ksepi_reflines
Definition: ksepi_implementation.e:261
#define KS_INIT_SEQLOC
Definition: KSFoundation.h:287
int rf2grad_end
Definition: KSFoundation.h:1467
int duration
Definition: KSFoundation.h:673
int ksepi_slicecheck
Definition: ksepi_implementation.e:197
KS_TRAP diffgrads[3]
Definition: ksepi_implementation.e:97
int ramptime
Definition: KSFoundation.h:671

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_kissoff_factor

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

◆ ksepi_rfstretch_exc

float ksepi_rfstretch_exc = 1.0 with {0.1,10.0, 1.0, VIS, "RF excitation stretch factor"}

◆ ksepi_fastexc3D

int ksepi_fastexc3D = TRUE with {FALSE, TRUE, TRUE, VIS, "Sel. RF exc (3D) 0:EXC_SPSP_3D 1:EXC_FAST_SPSP_3D",}

◆ ksepi_crusher_dephasing

float ksepi_crusher_dephasing = 6.0 with { 0.0, 100.0, 6.0, VIS, "crusher dephasing over slice [cycles]",}

◆ ksepi_gscalerfref

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

◆ ksepi_rfstretch_ref

float ksepi_rfstretch_ref = 1.0 with {0.1,10.0, 1.0, VIS, "RF refocusing stretch factor",}

◆ ksepi_bridgecrushers

int ksepi_bridgecrushers = FALSE with {FALSE, TRUE, FALSE, VIS, "Bridge RF ref crushers",}

◆ ksepi_t1value_to_null

int ksepi_t1value_to_null = T1_FAT_3T with {0, 5s, T1_FAT_3T, VIS, "T1 value to NULL [us]",}

◆ 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_kz_nacslines

int ksepi_kz_nacslines = 8 with {0, 64, 8, VIS, "#acslines 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_readout_mode

int ksepi_readout_mode = KS_EPI_BIPOLAR with {KS_EPI_BIPOLAR, KS_EPI_FLYBACK, KS_EPI_BIPOLAR, VIS, "EPI readout mode 0: bipolar 1:splitoddeven 2:flyback",}

◆ 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_echotime_shifting_fleet

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

◆ ksepi_fleet_flip

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

◆ ksepi_fleet_dda

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

◆ ksepi_fleet_num_ky

int ksepi_fleet_num_ky = 48 with {32, 256, 48, VIS, "Number of ky encodes for FLEET module",}

◆ ksepi_fleet_readout_mode

int ksepi_fleet_readout_mode = KS_EPI_SPLITODDEVEN with {KS_EPI_BIPOLAR, KS_EPI_FLYBACK, KS_EPI_SPLITODDEVEN, VIS, "FLEET EPI readout mode 0: bipolar 1:splitoddeven 2:flyback",}

◆ ksepi_fleet_nshots

int ksepi_fleet_nshots = 3 with {1, 128, 3, VIS, "# shots for FLEET",}

◆ 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 {1, 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_ref_nsegments

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

◆ ksepi_epiqfact

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

◆ ksepi_recvgain_mode

int ksepi_recvgain_mode = RG_CAL_MODE_HIGH_FIXED with {RG_CAL_MODE_MIN, RG_CAL_MODE_MAX, RG_CAL_MODE_HIGH_FIXED, VIS, "RecvGain - 0:Measured 1:8 2:5 3:Max",}

◆ ksepi_metadump

int ksepi_metadump = 0

◆ ksepi

Main EPI sequence (KSEPI_DATAGROUP_MAIN or KSEPI_DATAGROUP_MAIN_SPLITODDEVEN)

◆ ksepi_loopctrl

Scan loop control for the ksepi sequence (without inversion)

◆ ksepi_diffctrl

◆ ksepi_fleetseq

FLEET calibation sequence for parallel imaging (KSEPI_DATAGROUP_FLEET or KSEPI_DATAGROUP_FLEET_SPLITODDEVEN)

◆ ksepi_fleet_loopctrl

Scan loop control for the FLEET sequence

◆ ksepi_inv

Inversion module

◆ ksepi_inv_loopctrl

Scan loop control when using main sequence + inversion module

◆ ksepi_phaseencoding_memorypool

◆ ksepi_interechotime

int ksepi_interechotime = 0

◆ ksepi_echotime_shifting_shotdelay

float ksepi_echotime_shifting_shotdelay = 0.0

◆ ksepi_echotime_shifting_shotdelay_fleet

float ksepi_echotime_shifting_shotdelay_fleet = 0.0

◆ ksepi_echotime_shifting_sumdelay

int ksepi_echotime_shifting_sumdelay = 0

◆ ksepi_echotime_shifting_sumdelay_fleet

int ksepi_echotime_shifting_sumdelay_fleet = 0

◆ kacq

◆ 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_amp_scale

float ksepi_diffusion_amp_scale = 1.0 with {0.0, 1.0, 1.0, VIS, "Cap for scaling factor of 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_returnmode

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

◆ ksepi_diffusion_minramptime

int ksepi_diffusion_minramptime = 1ms with {0, 20ms, 1ms, VIS, "Minimum diffusion ramp time. If 0: syslimits used",}