KSFoundation  [October2024]
A platform for structured EPIC programming on GE MR systems
GERequired.e File Reference
#include "grad_rf_empty.globals.h"
#include "em_psd_ermes.in"
#include "stddef_ep.h"
#include "epicconf.h"
#include "pulsegen.h"
#include "epic_error.h"
#include "epic_loadcvs.h"
#include "InitAdvisories.h"
#include "psdiopt.h"
#include "filter.h"
#include "epicfuns.h"
#include <sokPortable.h>
#include "KSFoundation.h"
#include <psd_proto.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sar_pm.h"
#include "grad_rf_empty.h"
#include <sysDep.h>
#include <sysDepSupport.h>
#include <support_func.h>
#include <math.h>
#include "psdopt.h"
#include "predownload.in"
#include "cvinit.in"
#include <support_func.host.h>

Data Structures

struct  ks_kacq_coord_params_t
 

Macros

#define seq_name   ]_set
 
#define GEREQUIRED_E
 
#define CLINICAL_MODE   0
 
#define MAX_ENTRY_POINTS   15
 
#define MAX_SEQMODULES_DURATION_DEVIATION_FRACTION   0.0001
 
#define DEFAULT_SCAN_INFO_HEAD   0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0
 
#define DEFAULT_AXIAL_SCAN_INFO
 
#define DEFAULT_AX_SCAN_INFO_FREQ_LR   DEFAULT_AXIAL_SCAN_INFO
 
#define DEFAULT_AX_SCAN_INFO_FREQ_AP
 
#define DEFAULT_SAG_SCAN_INFO_FREQ_SI
 
#define DEFAULT_SAG_SCAN_INFO_FREQ_AP
 
#define DEFAULT_COR_SCAN_INFO_FREQ_SI
 
#define DEFAULT_COR_SCAN_INFO_FREQ_LR
 
#define KS_PSD_USE_APX   0
 

Typedefs

typedef int bool
 

Functions

 KS_SEQLENGTH (seq_name, seq_struct)
 
STATUS calcPulseParams (int p)
 
STATUS simscan (void)
 
STATUS GEReq_init_gradspecs (LOG_GRAD *loggrd, PHYS_GRAD *phygrd, float srfact)
 
STATUS GEReq_init_accelUI (int integeraccel, int maxaccel)
 
STATUS GEReq_eval_TRrange (int *slperpass, int *timetoadd_perTR, int requested_minacqs, int mintr, int maxtr, KS_SEQ_COLLECTION *seqcollection, int(*play_loop)(int, int, void **), int nargs, void **args)
 
STATUS GEReq_eval_TR (int *slperpass, int *timetoadd_perTR, int requested_minacqs, KS_SEQ_COLLECTION *seqcollection, int(*play_loop)(int, int, void **), int nargs, void **args)
 
STATUS GEReq_eval_rfscaling (KS_SEQ_COLLECTION *seqcollection)
 
STATUS GEReq_eval_checkTR_SAR_calcs (KS_SEQ_COLLECTION *seqcollection, s64 intended_time)
 
STATUS GEReq_eval_checkTR_SAR (KS_SEQ_COLLECTION *seqcollection, int nslices, int(*play_loop)(int, int, void **), int nargs, void **args)
 
STATUS GEReq_predownload_store_sliceplan (KS_SLICE_PLAN slice_plan)
 
STATUS GEReq_predownload_store_sliceplan_sms (const KS_SLICE_PLAN slice_plan, int sms_factor)
 
STATUS GEReq_predownload_store_sliceplan3D (int slices_in_slab, int slabs)
 
STATUS GEReq_predownload_setfilter_or_find_equivalent (FILTER_INFO *myfilter, FILTER_BLOCK_TYPE type)
 
int GEReq_get_num_used_slots ()
 
PSD_FILTER_GEN GEReq_get_maxsize_finfo (int n_prescan_slots)
 
STATUS GEReq_predownload_setfilter (FILTER_INFO *filt)
 
STATUS GEReq_echotrain_setfilters (KS_ECHOTRAIN *const echotrain)
 
STATUS GEReq_predownload_minimize_ps_filter_slots ()
 
STATUS GEReq_setfilters (KS_SEQ_COLLECTION *const seq_collection)
 
STATUS GEReq_predownload_genVRGF (const KS_READTRAP *const readtrap)
 
STATUS GEReq_predownload_genrowflip (KS_EPI *epi, int blipsign, int assetflag, int dorowflip)
 
STATUS GEReq_predownload_setrecon_writekacq (const KS_READTRAP *const readtrap, const KS_PHASER *const phaser, const KS_PHASER *const zphaser)
 
int ks_get_unique_y_from_pecoords (const KS_KSPACE_ACQ *kacq)
 
int ks_get_unique_z_from_pecoords (const KS_KSPACE_ACQ *kacq)
 
int ks_get_ynover_from_pecoords (const KS_KSPACE_ACQ *kacq)
 
int ks_get_znover_from_pecoords (const KS_KSPACE_ACQ *kacq)
 
int ks_get_ry_from_pecoords (const KS_KSPACE_ACQ *kacq)
 
int ks_get_rz_from_pecoords (const KS_KSPACE_ACQ *kacq)
 
int ks_get_cal_z_from_pecoords (const KS_KSPACE_ACQ *kacq)
 
int ks_get_cal_y_from_pecoords (const KS_KSPACE_ACQ *kacq)
 
ks_kacq_coord_params_t GEReq_kacq_get_params (const KS_KSPACE_ACQ *kacq)
 
STATUS GEReq_writekacq (const int nrecon_schedule_entries, KS_KACQ_RECONSHEDULE_ENTRY *recon_schedule, const int num_patterns, const KS_KSPACE_ACQ *ks_kacq)
 
STATUS GEReq_writekacq_from_coords (const KS_KSPACE_ACQ *kacq, const int nechoes)
 
STATUS GEReq_predownload_setrecon_accel_from_coords (const KS_KSPACE_ACQ *kacq, const int is_pf_y, const int nechoes)
 
STATUS GEReq_predownload_setrecon_accel (const KS_READTRAP *const readtrap, const KS_PHASER *const phaser, const KS_PHASER *const zphaser, int datadestination)
 
void GEReq_predownload_setrecon_phase (const KS_PHASER *const phaser, const float readfov, const int datadestination)
 
void GEReq_predownload_setrecon_readwave (const KS_READWAVE *const readwave, const int yres, const int xres, int imsize_policy, int datadestination)
 
void GEReq_predownload_setrecon_image (const int xres, const int yres, const float xfov, const float yfov, const ks_enum_imsize imsize_policy)
 
void GEReq_predownload_setrecon_readtrap (const KS_READTRAP *const readtrap, int datadestination)
 
void GEReq_predownload_setrecon_readphase (const KS_READTRAP *const readtrap, const KS_PHASER *const phaser, const KS_PHASER *const zphaser, int imsize_policy, int datadestination)
 
void GEReq_predownload_setrecon_annotations (int tsp, int readdur, int time2center, int echogap)
 
void GEReq_predownload_setrecon_annotations_readtrap (KS_READTRAP *readtrap, int echogap)
 
void GEReq_predownload_setrecon_annotations_readwave (KS_READWAVE *readwave, int echogap)
 
void GEReq_predownload_setrecon_annotations_epi (KS_EPI *epi, int echogap)
 
void GEReq_predownload_setrecon_voldata (int numvols, const KS_SLICE_PLAN slice_plan)
 
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)
 
STATUS GEReq_predownload_prescan_options (RG_CAL_MODE_E rg_cal_mode)
 
STATUS GEReq_cvinit (void)
 
STATUS GEReq_cveval (void)
 
void getAPxParam (optval *min, optval *max, optdelta *delta, optfix *fix, float coverage, int algorithm)
 
int getAPxAlgorithm (optparam *optflag, int *algorithm)
 
STATUS GEReq_cvcheck (void)
 
STATUS GEReq_predownload (void)
 
void GEReq_pulsegenBegin (void)
 
void GEReq_pulsegenEnd (void)
 
int GEReq_endofpass ()
 
int GEReq_endofscan ()
 
int GEReq_endofpassandscan ()
 
void dummylinks (void)
 
void GEReq_initRSP (void)
 

Variables

RF_PULSE_INFO rfpulseInfo [RF_FREE] = { {0, 0} }
 
int avail_image_time
 
ifndef ACT_TR_EXISTS int act_tr
 
endif SCAN_INFO ks_scan_info [SLTAB_MAX] = {DEFAULT_AXIAL_SCAN_INFO}
 
KS_SLICE_PLAN ks_slice_plan = KS_INIT_SLICEPLAN
 
int ks_sarcheckdone = FALSE
 
char ks_psdname [256]
 
int ks_perform_slicetimeplot = FALSE
 
KS_SEQ_CONTROL seqctrl_passpack = KS_INIT_SEQ_CONTROL
 
int obl_debug = 0 with {0, 1, 0, INVIS, "On(=1) to print messages for obloptimize",}
 
int obl_method = PSD_OBL_OPTIMAL with {PSD_OBL_RESTRICT, PSD_OBL_OPTIMAL, PSD_OBL_OPTIMAL, INVIS, "On(=1) to optimize the targets based on actual rotation matrices",}
 
int filter_echo1 = 0 with {, , , INVIS, "Scan filter slot number needed for prescan",}
 
int pw_passpacket = 50ms with {10ms, 1000ms, 50ms, VIS, "Duration of the passpacket sequence",}
 
int ks_rfconf = ENBL_RHO1 + ENBL_THETA + ENBL_OMEGA + ENBL_OMEGA_FREQ_XTR1
 
int ks_simscan = 1 with {0, 1, 1, VIS, "Simulate slice locations if 1 (and in simulation)",}
 
float ks_srfact = 1.0 with {0.01, 3.0, 1.0, VIS, "Slewrate factor (low value = slower gradients)",}
 
float ks_qfact = 1.0 with {0.1, 40.0, 1.0, VIS, "Quietness factor",}
 
int ks_plot_filefmt = KS_PLOT_MAKEPNG with {KS_PLOT_OFF,KS_PLOT_MAKEPNG,KS_PLOT_MAKEPNG, VIS, "Plot format 0:off 1:PDF 2:SVG 3:PNG"}
 
int ks_plot_kstmp = FALSE with {FALSE,TRUE,FALSE, VIS, "0: off 1:Copy plots to mrraw/kstmp"}
 
int ks_compress_ps_filter_slots = FALSE with {FALSE,TRUE,FALSE, VIS, "Minimize the number of filterslots for prescan"}
 
int ks_clinicalmode = CLINICAL_MODE with {0, 1, CLINICAL_MODE, VIS, "Clinical mode: on=1 / off=0"}
 
float maxB1 [MAX_ENTRY_POINTS]
 
float maxB1Seq
 
short debugstate
 
short viewtable [513]
 
PSD_EXIT_ARG psdexitarg
 
int rspent
 
int rspdda
 
int rspbas
 
int rspvus
 
int rspgy1
 
int rspasl
 
int rspesl
 
int rspchp
 
int rspnex
 
int rspslq
 
int rspsct
 
int rsprep
 
short chopamp
 
int seqCount
 
int view
 
int excitation
 
int debug
 
const CHAR * entry_name_list [ENTRY_POINT_MAX]
 

Detailed Description

This file has several sections that should be @inline'd for a main pulse sequence

written entirely in KSFoundation EPIC. See instructions for each section on where to @inline

Macro Definition Documentation

◆ seq_name

#define seq_name   ]_set

◆ GEREQUIRED_E

#define GEREQUIRED_E

◆ CLINICAL_MODE

#define CLINICAL_MODE   0

◆ MAX_ENTRY_POINTS

#define MAX_ENTRY_POINTS   15

◆ MAX_SEQMODULES_DURATION_DEVIATION_FRACTION

#define MAX_SEQMODULES_DURATION_DEVIATION_FRACTION   0.0001

◆ DEFAULT_SCAN_INFO_HEAD

#define DEFAULT_SCAN_INFO_HEAD   0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0

◆ DEFAULT_AXIAL_SCAN_INFO

#define DEFAULT_AXIAL_SCAN_INFO
Value:
{ DEFAULT_SCAN_INFO_HEAD, {1.0, 0.0, 0.0, \
0.0, 1.0, 0.0, \
0.0, 0.0, 1.0}}
#define DEFAULT_SCAN_INFO_HEAD
Definition: GERequired.e:155

◆ DEFAULT_AX_SCAN_INFO_FREQ_LR

#define DEFAULT_AX_SCAN_INFO_FREQ_LR   DEFAULT_AXIAL_SCAN_INFO

◆ DEFAULT_AX_SCAN_INFO_FREQ_AP

#define DEFAULT_AX_SCAN_INFO_FREQ_AP
Value:
{ DEFAULT_SCAN_INFO_HEAD, {0.0, 1.0, 0.0, \
-1.0, 0.0, 0.0, \
0.0, 0.0, 1.0}}
#define DEFAULT_SCAN_INFO_HEAD
Definition: GERequired.e:155

◆ DEFAULT_SAG_SCAN_INFO_FREQ_SI

#define DEFAULT_SAG_SCAN_INFO_FREQ_SI
Value:
{ DEFAULT_SCAN_INFO_HEAD, {0.0, 0.0, 1.0, \
0.0, 1.0, 0.0, \
-1.0, 0.0, 0.0}}
#define DEFAULT_SCAN_INFO_HEAD
Definition: GERequired.e:155

◆ DEFAULT_SAG_SCAN_INFO_FREQ_AP

#define DEFAULT_SAG_SCAN_INFO_FREQ_AP
Value:
{ DEFAULT_SCAN_INFO_HEAD, {0.0, 0.0, 1.0, \
1.0, 0.0, 0.0, \
0.0, 1.0, 0.0}}
#define DEFAULT_SCAN_INFO_HEAD
Definition: GERequired.e:155

◆ DEFAULT_COR_SCAN_INFO_FREQ_SI

#define DEFAULT_COR_SCAN_INFO_FREQ_SI
Value:
{ DEFAULT_SCAN_INFO_HEAD, {0.0, 1.0, 0.0, \
0.0, 0.0, 1.0, \
1.0, 0.0, 0.0}}
#define DEFAULT_SCAN_INFO_HEAD
Definition: GERequired.e:155

◆ DEFAULT_COR_SCAN_INFO_FREQ_LR

#define DEFAULT_COR_SCAN_INFO_FREQ_LR
Value:
{ DEFAULT_SCAN_INFO_HEAD, {-1.0, 0.0, 0.0, \
0.0, 0.0, 1.0, \
0.0, 1.0, 0.0}}
#define DEFAULT_SCAN_INFO_HEAD
Definition: GERequired.e:155

◆ KS_PSD_USE_APX

#define KS_PSD_USE_APX   0

Typedef Documentation

◆ bool

typedef int bool

Function Documentation

◆ KS_SEQLENGTH()

KS_SEQLENGTH ( seq_name  ,
seq_struct   
)

Creates a hardware sequence for the current sequence module

This EPIC macro is adapted from GE's EPIC macro SEQLENGTH. The seqctrl (KS_SEQ_CONTROL) struct for the current sequence module is passed in as the second argument to this function, where seqctrl.duration holds the information on the duration of the sequence module and passed on to createseq(). During scanning, ks_scan_playsequence(), which takes a KS_SEQ_CONTROL struct as input, internally calls boffset() to make a real-time hardware switch to this sequence module by passing in seqctrl.handle.offset set by KS_SEQLENGTH().

KS_SEQLENGTH() must be called in pulsegen() after the sequence (module) has been layed out using various ks_pg_*** calls. It must also be after GEReq_pulsegenBegin() and before GEReq_pulsegenEnd() and buildinstr(). The first argument to KS_SEQLENGTH() is GE's name of the pulse sequence module, which by convention usually begins with "seq***". The hardware sequence handle is then named off_seq*** and this handle is stored in seqctrl.handle.offset.

EPIC macro Parameters

  • arg 1: Name of the sequence module (only used for this function call)
  • arg 2: The KS_SEQ_CONTROL struct for the current sequence module
65  {
66 
67  var: {
68  #ifndef $[seq_name]_set
69  #define $[seq_name]_set
70  #else
71  #error KS_SEQLENGTH: Sequence name $[seq_name] (arg 1) already taken
72  #endif
73  SEQUENCE_ENTRIES off_$[seq_name];
74  WF_PULSE $[seq_name];
75  #if defined(HOST_TGT)
76  int idx_$[seq_name]; /* sequence entry index */
77  #endif
78  }
79  insert: predownload => {
80  /* dont indent the closing bracket */
81 }
82  insert: cvinit => {
83  /* dont indent the closing bracket */
84 }
85 
86  subst: {
87  {
88  if ($[seq_struct].duration > 0) {
89 
90  if ($[seq_struct].duration - $[seq_struct].ssi_time < 0) {
91 
92  ks_error("KS_SEQLENGTH (%s): (.duration - .ssi_time) is negative", $[seq_struct].description);
93 
94  } else {
95 
96  STATUS status = pulsename(&$[seq_name], "$[seq_name]");
97  if (status != SUCCESS) {
98  ks_error("KS_SEQLENGTH (%s): pulsename($[seq_name]) failed", $[seq_struct].description);
99  }
100  status = createseq(&$[seq_name], $[seq_struct].duration - $[seq_struct].ssi_time, off_$[seq_name]);
101  if (status != SUCCESS) {
102  ks_error("KS_SEQLENGTH (%s): createseq($[seq_name]) failed", $[seq_struct].description);
103  }
104 
105  #if defined(HOST_TGT)
106  /* Update sequence counter and get current sequence entry index */
107  status = updateIndex( &idx_$[seq_name] );
108  if (status != SUCCESS) {
109  ks_error("KS_SEQLENGTH (%s): updateIndex($[seq_name]) failed", $[seq_struct].description);
110  }
111  printDebug( DBLEVEL1, (dbLevel_t)seg_debug, "KS_SEQLENGTH",
112  "idx_$[seq_name] = %d\n", idx_$[seq_name] );
113  $[seq_struct].handle.index = idx_$[seq_name];
114  #endif
115  /* copy seqyence_enties to the KS_SEQ seq_struct */
116  $[seq_struct].handle.offset = off_$[seq_name];
117  $[seq_struct].handle.pulse = &$[seq_name];
118  } /* duration - ssi_time > 0 */
119 
120  } /* duration > 0 */
121  }
122  }
123 
124 }
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
#define seq_name
STATUS predownload(void)
Definition: ksepi.e:237
STATUS cvinit(void)
Definition: ksepi.e:88

◆ calcPulseParams()

STATUS calcPulseParams ( int  p)

Mandatory GE function. Includes predownload.in

Return values
STATUSSUCCESS or FAILURE
323  {
324 
325 #include "predownload.in" /* include 'canned' predownload code */
326  p = 0;
327  return SUCCESS;
328 
329 } /* calcPulseParams() */

◆ simscan()

STATUS simscan ( void  )

Simulate scan locations in simulation (WTools)

Return values
STATUSSUCCESS or FAILURE
340  {
341 
342 #ifndef PSD_HW
343 
344  int i, j;
345  int num_slice;
346  float z_delta; /* change in z_loc between slices */
347  float r_delta; /* change in r_loc between slices */
348  double alpha, beta, gamma; /* rotation angles about x, y, z respectively */
349 
350  num_slice = opslquant;
351 
352  r_delta = opfov / num_slice;
353  z_delta = opslthick + opslspace;
354 
355  ks_scan_info[0].optloc = - 0.5 * z_delta * (num_slice - 1);
356  ks_scan_info[0].oprloc = 0;
357 
358  for (i = 1; i < 9; i++)
359  ks_scan_info[0].oprot[i] = 0.0;
360 
361  switch (exist(opplane)) {
362  case PSD_AXIAL:
363  ks_scan_info[0].oprot[0] = 1.0;
364  ks_scan_info[0].oprot[4] = 1.0;
365  ks_scan_info[0].oprot[8] = 1.0;
366  break;
367  case PSD_SAG:
368  ks_scan_info[0].oprot[2] = 1.0;
369  ks_scan_info[0].oprot[4] = 1.0;
370  ks_scan_info[0].oprot[6] = 1.0;
371  break;
372  case PSD_COR:
373  ks_scan_info[0].oprot[2] = 1.0;
374  ks_scan_info[0].oprot[6] = 1.0;
375  ks_scan_info[0].oprot[7] = 1.0;
376  break;
377  case PSD_OBL:
378  alpha = PI / 4.0; /* rotation about x (applied first) */
379  beta = 0; /* rotation about y (applied 2nd) */
380  gamma = 0; /* rotation about z (applied 3rd) */
381  ks_scan_info[0].oprot[0] = cos(gamma) * cos(beta);
382  ks_scan_info[0].oprot[1] = cos(gamma) * sin(beta) * sin(alpha) -
383  sin(gamma) * cos(alpha);
384  ks_scan_info[0].oprot[2] = cos(gamma) * sin(beta) * cos(alpha) +
385  sin(gamma) * sin(alpha);
386  ks_scan_info[0].oprot[3] = sin(gamma) * cos(beta);
387  ks_scan_info[0].oprot[4] = sin(gamma) * sin(beta) * sin(alpha) +
388  cos(gamma) * cos(alpha);
389  ks_scan_info[0].oprot[5] = sin(gamma) * sin(beta) * cos(alpha) -
390  cos(gamma) * sin(alpha);
391  ks_scan_info[0].oprot[6] = -sin(beta);
392  ks_scan_info[0].oprot[7] = cos(beta) * sin(alpha);
393  ks_scan_info[0].oprot[8] = cos(beta) * cos(alpha);
394  break;
395  }
396 
397  for (i = 1; i < num_slice; i++) {
398  ks_scan_info[i].optloc = ks_scan_info[i - 1].optloc + z_delta;
399  ks_scan_info[i].oprloc = i * r_delta;
400  for (j = 0; j < 9; j++)
401  ks_scan_info[i].oprot[j] = ks_scan_info[0].oprot[j];
402  }
403 
404 #endif /* ifdef SIM */
405 
406  return SUCCESS;
407 
408 } /* simscan() */
float opfov
float opslthick
endif SCAN_INFO ks_scan_info[SLTAB_MAX]
Definition: GERequired.e:240

◆ GEReq_init_gradspecs()

STATUS GEReq_init_gradspecs ( LOG_GRAD *  loggrd,
PHYS_GRAD *  phygrd,
float  srfact 
)

Initialize logical and physical gradient specifications

This function calls inittargets() to get the physical gradient characteristics from the MR-system, followed by a call to obloptimize() (slice angulation dependence) to get the logical gradient specifications for the current slice angulation.

The ramp times (loggrd.xrt/yrt/zrt) are quite conservative (and longer than the ramptimes for phygrd). Preliminary testing indicates that the difference between the loggrd and phygrad structs can be reduced by a factor of two (not very scientific!) as a standard measure.

For further control over the slewrate, the srfact argument is passed to ks_init_slewratecontrol(), which can both slow down and increase the gradient slewrate.

Parameters
[out]loggrdThe global logical gradient specification struct (dependent on slice angulation via global SCAN_INFO scan_info[] struct).
[out]phygrdThe global physical gradient struct
[in]srfact
Return values
STATUSSUCCESS or FAILURE
435  {
436  int initnewgeo = 1;
437 
438  /* default gradient specs */
440 
441  /* optimal loggrd based on current slice angulations */
442  if (obloptimize_epi(loggrd, phygrd, scan_info, exist(opslquant),
443  ((obl_method==PSD_OBL_RESTRICT) ? 4 /*oblique plane*/ : opphysplane), exist(opcoax), (int) obl_method,
444  exist(obl_debug), &initnewgeo, cfsrmode) == FAILURE) {
445  return ks_error("ks_init_loggrd: obloptimize failed");
446  }
447 
448  /* reduce slewrate if srfact < 1 */
449  if (ks_init_slewratecontrol(loggrd, phygrd, srfact) == FAILURE)
450  return FAILURE;
451 
452  return SUCCESS;
453 
454 } /* GEReq_init_gradspecs() */
STATUS inittargets(LOG_GRAD *lgrad, PHYS_GRAD *pgrad)
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int obl_method
Definition: GERequired.e:262
PHYS_GRAD phygrd
LOG_GRAD loggrd
STATUS obloptimize_epi(LOG_GRAD *lgrad, PHYS_GRAD *pgrad, SCAN_INFO *scaninfotab, INT slquant, INT plane_type, INT coaxial, INT method, INT debug, INT *newgeo, INT srmode)
SCAN_INFO scan_info[]
int obl_debug
Definition: GERequired.e:261
STATUS ks_init_slewratecontrol(LOG_GRAD *loggrd, PHYS_GRAD *phygrd, float srfact) WARN_UNUSED_RESULT
Changes existing (globally used) loggrd and phygrd structs (set up by inittargets() in e...
Definition: KSFoundation_host.c:164
int cfsrmode

◆ GEReq_init_accelUI()

STATUS GEReq_init_accelUI ( int  integeraccel,
int  maxaccel 
)

Sets up the menu for parallel imaging (ARC or ASSET) with max/min range

Parameters
[in]integeraccelFlag to make acceleration menu contain only integer acceleration factors enums: KS_ARCMENU_FRACTACCEL (0), KS_ARCMENU_INTACCEL (1)
[in]maxaccelMaximum allowed acceleration factor for the sequence
Return values
STATUSSUCCESS or FAILURE
468  {
469 
470  /* Acceleration menu */
471  cfaccel_ph_maxstride = maxaccel;
472  cvmax(opaccel_ph_stride, cfaccel_ph_maxstride);
473  avminaccel_ph_stride = 1.0;
474  avmaxaccel_ph_stride = cfaccel_ph_maxstride;
475  piarccoilrestrict = 1; /* disable ARC option for single-channel coil (cf. epic.h) */
476 
477  if (KS_3D_SELECTED) { /* PSD_3D or PSD_3DM */
478  cfaccel_sl_maxstride = maxaccel;
479  cvmax(opaccel_sl_stride, cfaccel_sl_maxstride);
480  avminaccel_sl_stride = 1.0;
481  avmaxaccel_sl_stride = cfaccel_sl_maxstride;
482  }
483 
484  if ((oparc || opasset == ASSET_SCAN) && maxaccel > 1) {
485  if (integeraccel) {
486  piaccel_phnub = 1 + maxaccel;
487  piaccel_phval2 = 1.0;
488  piaccel_phval3 = 2.0;
489  piaccel_phval4 = 3.0;
490  piaccel_phval5 = 4.0;
491  piaccel_phval6 = 5.0;
492  piaccel_phedit = 0; /* don't allow user to type in value */
493  } else {
494  piaccel_phnub = IMin(2, 6, maxaccel * 2);
495  piaccel_phval2 = 1.0;
496  piaccel_phval3 = 1.5;
497  piaccel_phval4 = 2.0;
498  piaccel_phval5 = 2.5;
499  piaccel_phval6 = 3.0;
500  piaccel_phedit = 1;
501  }
502  piaccel_ph_stride = 2.0;
503  if (KS_3D_SELECTED) {
504  if (integeraccel) {
505  piaccel_slnub = 1 + maxaccel;
506  piaccel_slval2 = 1.0;
507  piaccel_slval3 = 2.0;
508  piaccel_slval4 = 3.0;
509  piaccel_slval5 = 4.0;
510  piaccel_slval6 = 5.0;
511  piaccel_sledit = 0; /* don't allow user to type in value */
512  } else {
513  piaccel_slnub = IMin(2, 6, maxaccel * 2);
514  piaccel_slval2 = 1.0;
515  piaccel_slval3 = 1.5;
516  piaccel_slval4 = 2.0;
517  piaccel_slval5 = 2.5;
518  piaccel_slval6 = 3.0;
519  piaccel_sledit = 1;
520  }
521  piaccel_sl_stride = 1.0;
522  } else {
523  piaccel_slnub = 0;
524  }
525  } else {
526  piaccel_phnub = 0;
527  piaccel_slnub = 0;
528  cvoverride(opaccel_ph_stride, 1.0, PSD_FIX_OFF, PSD_EXIST_OFF);
529  cvoverride(opaccel_sl_stride, 1.0, PSD_FIX_OFF, PSD_EXIST_OFF);
530  }
531 
532  return SUCCESS;
533 
534 } /* GEReq_init_accelUI() */
#define KS_3D_SELECTED
Definition: KSFoundation.h:242

◆ GEReq_eval_TRrange()

STATUS GEReq_eval_TRrange ( int *  slperpass,
int *  timetoadd_perTR,
int  requested_minacqs,
int  mintr,
int  maxtr,
KS_SEQ_COLLECTION seqcollection,
int(*)(int, int, void **)  play_loop,
int  nargs,
void **  args 
)

Calculate the number of slices per TR and TR padding time (2D imaging)


2024 UPDATE: THIS FUNCTION IS ONLY USED BY KSGRE_TUTORIAL.E AND DEPCREATED PSDS.

THE NEW PSDS USE KSSCAN_LOOP_CONTROL CONTAINING KS_PHASEENCODING_PLAN AND KS_SLICETIMING FOR THE SCAN LOOP.

This function calculates the number of slices that can fit in one TR (optr) based on the duration and occurences of the sequence modules in the sequence collection (KS_SEQ_COLLECTION) determined by calling the sequence sliceloop (wrapper) function.

As the number of arguments to the sequence's sliceloop is psd-dependent, the function pointer play_loop must be a wrapper function to the sliceloop function taking standardized input arguments (int) nargs and (void **) args. This sliceloop wrapper function must be on the form: int sliceloop_nargs(int slperpass, int nargs, void **args); returning the duration in [us] to play out slperpass number of slices. If the sliceloop function does not need any additional input arguments, nargs = 0, and args = NULL.

The minimum allowed TR is determined by ks_eval_mintr(), which honors SAR/heating limitations. If opautotr = 1, optr will be updated here, otherwise if optr is too short, an error will be returned to the operator.

The calling function can specify the minimum acqs that are allowed, as well as a minimum and maximum TR interval. Setting maxtr = 0 disables the upper TR limit. Setting requested_minacqs <= 1, disables the min acqs requirement.

This function should be called at the end of cveval() after all sequence modules have been set up and dry-runned on host by calling each sequence module's ****_pg() function. See also the documentation for KS_SEQ_CONTROL and KS_SEQ_COLLECTION.

Parameters
[out]slperpassNumber of slices that can fit within each TR
[out]timetoadd_perTRThe total time in [us] that must be distributed manually to one or more sequence modules after the call to GEReq_eval_TR() in order to meet the desired TR
[in]requested_minacqsThe desired minimum number of acquisitions (passes)
[in]mintrLowest allowed TR in [us]
[in]maxtrHighest allowed TR in [us]. 0: Disabled
[in,out]seqcollectionPointer to the KS_SEQ_COLLECTION struct holding all sequence modules
[in]play_loopFunction pointer to (the wrapper function to) the sliceloop function of the sequence
[in]nargsNumber of extra input arguments to the sliceloop wrapper function.
[in]argsVoid pointer array pointing to the variables containing the actual values needed for the sequence's sliceloop function
Return values
STATUSSUCCESS or FAILURE
586  {
587  STATUS status;
588  int numacqs = 0;
589  int i;
590  int numrfexclocations = (KS_3D_SELECTED) ? exist(opvquant) : exist(opslquant);
591  int slicetime;
592  int nslices_perTR = KS_NOTSET;
593  int nslices_shortest_scantime = KS_NOTSET;
594  int lowest_scantime = KS_NOTSET;
595  int singleslice_time = KS_NOTSET;
596  int requested_maxslices = KS_NOTSET;
597  int maxslices_time = KS_NOTSET;
598 
599  /* check if the hardware limts have already been checked */
600  if (seqcollection->hwlimitsdone != TRUE) {
601  return ks_error("%s: hardware limits must be checked before calling this function", __FUNCTION__);
602  }
603 
604  if (seqcollection == NULL || seqcollection->numseq == 0) {
605  return ks_error("%s: Please add pulse sequence modules to the sequence collection before calling this function", __FUNCTION__);
606  }
607 
608  if (mintr < 0 || maxtr < 0) {
609  return ks_error("%s: min/max TR cannot be negative", __FUNCTION__);
610  } else if ((maxtr > 0) && (maxtr <= mintr)) {
611  return ks_error("%s: max TR must be > minTR, or 0 (disabled)", __FUNCTION__);
612  }
613 
614  /* make sure seqctrl.duration at least equal to seqctrl.min_duration */
616  KS_RAISE(status);
617 
618  singleslice_time = ks_eval_mintr(1, seqcollection, play_loop, nargs, args);
619  if (singleslice_time <= 0) return FAILURE;
620 
621  if ((maxtr > 0) && (maxtr < singleslice_time)) {
622  return ks_error("%s: Max TR must be > %.1f ms", __FUNCTION__, singleslice_time / 1000.0);
623  }
624  if ((mintr > 0) && (mintr < singleslice_time)) {
625  return ks_error("%s: Min TR must be > %.1f ms", __FUNCTION__, singleslice_time / 1000.0);
626  }
627  if ((maxtr > 0) && ((maxtr - mintr) < singleslice_time)) {
628  return ks_error("%s: The TR interval must be > %.1f ms", __FUNCTION__, singleslice_time / 1000.0);
629  }
630 
631  /* #acqs cannot exceed #slices. If sequential scanning, #acqs = #slices */
632  if (requested_minacqs < 1) {
633  requested_minacqs = 1;
634  } else if ((requested_minacqs > numrfexclocations) || (opirmode == TRUE)) {
635  requested_minacqs = numrfexclocations;
636  }
637  requested_maxslices = CEIL_DIV(numrfexclocations, requested_minacqs);
638  maxslices_time = ks_eval_mintr(requested_maxslices, seqcollection, play_loop, nargs, args);
639 
640 
641 
642  if (opautotr) { /* AutoTR: User selected pitrval2 = PSD_MINIMUMTR */
643 
644  if (maxtr > 0 || mintr > 0) { /* in-range autoTR */
645 
646  /* Check which combination that results in the lowest scan time, and max/min # slices in range */
647  for (i = 1; i <= numrfexclocations; i++) {
648  numacqs = CEIL_DIV(numrfexclocations, i);
649  slicetime = ks_eval_mintr(i, seqcollection, play_loop, nargs, args);
650  if (slicetime >= mintr && (maxtr == 0 || slicetime <= maxtr) && (numacqs >= requested_minacqs)) {
651  if (lowest_scantime == KS_NOTSET) {
652  nslices_shortest_scantime = i;
653  lowest_scantime = slicetime * numacqs;
654  } else if (slicetime * numacqs <= lowest_scantime * 1.01) {
655  /* 1.01 to avoid round-off effects of slicetime and to slightly favor fewer acqs and longer TRs
656  when the scantime is nearly identical */
657  nslices_shortest_scantime = i;
658  lowest_scantime = slicetime * numacqs;
659  }
660  }
661  }
662 
663  if (lowest_scantime == KS_NOTSET) {
664  /* failed to find solution within the interval, the range is probably too high for the set
665  of slices. Need to add padding to reach mintr. This
666  is done by setting optr = avmintr = mintr (see also timetoadd_perTR below)*/
667  if (maxslices_time < mintr) {
668  nslices_perTR = requested_maxslices;
669  avmintr = mintr;
670  } else {
671  return ks_error("%s: Programming error", __FUNCTION__);
672  }
673  } else {
674  nslices_perTR = nslices_shortest_scantime;
675  avmintr = ks_eval_mintr(nslices_perTR, seqcollection, play_loop, nargs, args);
676  }
677 
678  } else { /* minimum TR (using requested_minacqs) */
679 
680  nslices_perTR = requested_maxslices;
681  avmintr = ks_eval_mintr(nslices_perTR, seqcollection, play_loop, nargs, args);
682 
683  }
684 
685  avmaxtr = avmintr;
686  cvoverride(optr, avmintr, PSD_FIX_ON, PSD_EXIST_ON);
687 
688  } else { /* Manual TR */
689 
690  avmintr = singleslice_time;
691  avmaxtr = _optr.maxval;
692 
693  /* how many slices can we MAXIMALLY fit in one TR ? */
694  if (opirmode == 1) { /* sequential */
695  nslices_perTR = 1;
696  } else {
697  if (existcv(optr)) {
698  if (optr < avmintr)
699  return ks_error("%s: Increase the TR to %.1f ms", __FUNCTION__, avmintr / 1000.0);
700  if ((mintr > 0) && (optr < mintr))
701  return ks_error("%s: Increase the TR to %.1f ms", __FUNCTION__, mintr / 1000.0);
702  if ((maxtr > 0) && (optr > maxtr))
703  return ks_error("%s: Decrease the TR to %.1f ms", __FUNCTION__, maxtr / 1000.0);
704  }
705  nslices_perTR = ks_eval_maxslicespertr(exist(optr), seqcollection, play_loop, nargs, args);
706  nslices_perTR = IMax(2, 1, nslices_perTR); /* safeguard against < 1 */
707  }
708 
709  } /* Auto/Manual TR */
710 
711 
712  /* how many acqs (runs) do we need to get all prescribed slices ? */
713  numacqs = CEIL_DIV(numrfexclocations, nslices_perTR);
714 
715  /* how many slices SHOULD we play out per pass (keeping numrfexclocations and numacqs)?
716  This may be less than nslices_perTR depending on divisibility */
717  *slperpass = CEIL_DIV(numrfexclocations, numacqs); /* round up */
718 
719  /* run once more with the actual number of slices per TR, mostly so that ks_eval_hwlimits()->ks_eval_rflimits() will set the
720  description of `optr` correctly */
721  ks_eval_mintr(*slperpass, seqcollection, play_loop, nargs, args);
722 
723  /* run before each call to function pointer `play_loop()` (next line) to set all `seqctrl.ninst` to 0 */
725 
726  /* Update seqcollection.seqctrl[*].ninst given '*slperpass' number of slices
727  time [us] for one sequence playout incl. the SSI time and necessary dead time to
728  make up the expected TR. To be used in KS_SEQLENGTH() in pulsegen() */
729  *timetoadd_perTR = exist(optr) - play_loop(*slperpass, nargs, args);
730 
731  /* prevent further addition of new sequence modules */
733 
734  /* Flag that we have completed this function */
735  /* seqcollection->evaltrdone = TRUE; */
736 
737 
738 
739  /* Set UI and advisory panel variables */
740  avail_image_time = RDN_GRD(exist(optr));
742  ihtr = act_tr; /* image header TR */
743 
744  avminslquant = 1;
745  if (KS_3D_SELECTED == FALSE) {
746  avmaxslquant = nslices_perTR; /* UI value ("Max # Slices:") */
747  avmaxacqs = numacqs; /* UI value ("# of Acqs:") */
748  } else {
749  avmaxslquant = 2048;
750  avmaxacqs = 1;
751  }
752 
753  return SUCCESS;
754 
755 } /* GEReq_eval_TRrange() */
int ks_eval_mintr(int nslices, KS_SEQ_COLLECTION *seqcollection, int(*play_loop)(int, int, void **), int nargs, void **args)
Returns the minimum TR based on the content of a slice loop, adding additional time due to SAR and ha...
Definition: KSFoundation_host.c:5890
#define KS_NOTSET
Definition: KSFoundation.h:115
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
int mode
Definition: KSFoundation.h:1265
STATUS ks_eval_seqcollection_durations_atleastminimum(KS_SEQ_COLLECTION *seqcollection) WARN_UNUSED_RESULT
Assures the .duration fields of all sequence modules being part of the sequence collection (KS_SEQ_CO...
Definition: KSFoundation_host.c:4992
ifndef ACT_TR_EXISTS int act_tr
Definition: GERequired.e:235
int ks_eval_maxslicespertr(int TR, KS_SEQ_COLLECTION *seqcollection, int(*play_loop)(int, int, void **), int nargs, void **args)
Returns the maximum number of slices that can be played out in one TR, honoring SAR and hardware cons...
Definition: KSFoundation_host.c:5904
#define KS_RAISE(status)
Definition: KSFoundation.h:190
int avail_image_time
Definition: GERequired.e:233
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
int hwlimitsdone
Definition: KSFoundation.h:1267
Definition: KSFoundation.h:2358
_cvint _optr
int numseq
Definition: KSFoundation.h:1264

◆ GEReq_eval_TR()

STATUS GEReq_eval_TR ( int *  slperpass,
int *  timetoadd_perTR,
int  requested_minacqs,
KS_SEQ_COLLECTION seqcollection,
int(*)(int, int, void **)  play_loop,
int  nargs,
void **  args 
)

Calculate the number of slices per TR and TR padding time (2D imaging)


2024 UPDATE: THIS FUNCTION IS ONLY USED BY KSGRE_TUTORIAL.E AND DEPCREATED PSDS.

THE NEW PSDS USE KSSCAN_LOOP_CONTROL CONTAINING KS_PHASEENCODING_PLAN AND KS_SLICETIMING FOR THE SCAN LOOP.

771  {
772 
773  return GEReq_eval_TRrange(slperpass, timetoadd_perTR, requested_minacqs, 0, 0, seqcollection, play_loop, nargs, args);
774 
775 } /* GEReq_eval_TR() */
STATUS GEReq_eval_TRrange(int *slperpass, int *timetoadd_perTR, int requested_minacqs, int mintr, int maxtr, KS_SEQ_COLLECTION *seqcollection, int(*play_loop)(int, int, void **), int nargs, void **args)
Calculate the number of slices per TR and TR padding time (2D imaging)
Definition: GERequired.e:585
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:82

◆ GEReq_eval_rfscaling()

STATUS GEReq_eval_rfscaling ( KS_SEQ_COLLECTION seqcollection)

Performs RF scaling of all RF pulses in the KS_SEQ_COLLECTION and Prescan

RF scaling is a complicated process across RF pulses in scan (multiple sequence modules) and prescan, where the desired flip angles should be met partly using the maxB1 info for each RF pulse and scale it relative to the prescan result. This is done via a combination of scan and prescan attenuation factors (xmtaddScan) in the entry_point_table[], an extra global scaling factor, and change of the (instruction) amplitude of each RF pulse.

This function performs all these tasks using a KS_SEQ_COLLECTION as input. The sequence collection struct contains one KS_SEQ_CONTROL struct for each sequence module, which via the field gradrf.rfptr[] has access to all KS_RF objects in the sequence module. As the ***_pg() function for each sequence module should have been called prior to this function, the number of occurrences of each RF pulse is known. Moreover, the rfstat specification for every RF pulse is located in: seqcollection->seqctrl[]->gradrf->rfptr[]->rf.rfpulse which is used by ks_eval_seqcollection2rfpulse() to rewrite the global rfpulse[] struct array required by GE's RF scaling functions peakB1() and setScale().

At the end of this function, the seqcollection mode is locked, preventing accidental addition of new sequence modules to the seqcollection using ks_eval_addtoseqcollection(). Moreover, each sequence module will have its rfscalingdone field set to TRUE to signal to ks_pg_rf() that the RF pulse belonging to that sequence module has indeed been RF scaled properly. This extra safety mechanism makes it difficult to use ks_pg_rf() without first passing through this function and have the seqcollection struct set up.

Parameters
[in,out]seqcollectionPointer to the KS_SEQ_COLLECTION struct holding all sequence modules
Return values
STATUSSUCCESS or FAILURE
808  {
809  int i;
810  STATUS status;
811 
812 
813  if (seqcollection == NULL || seqcollection->numseq == 0) {
814  return ks_error("%s: Please add pulse sequence modules to the sequence collection before calling this function", __FUNCTION__);
815  }
816 
817  /* use global rfpulse[] array (that is also featuring in Prescan.e) */
818  for (i = 0; i < KS_MAXUNIQUE_RF; i++) {
819  rfpulse[i].activity = 0;
820  }
821 
822  /* Update the global RF pulse array rfpulse[] with the contents of the RF pulses in the sequence modules.
823  This also includes resetting all .activity fields to zero for the first KS_MAXUNIQUE_RF elements in rfpulse[] */
825  KS_RAISE(status);
826 
827 
828  /* find the peak B1 for each entry point and the max B1 across all entry points */
829  status = findMaxB1Seq(&maxB1Seq, maxB1, MAX_ENTRY_POINTS, rfpulse, RF_FREE);
830  if (status != SUCCESS) {
831  return ks_error("%s: findMaxB1Seq() failed", __FUNCTION__);
832  }
833 
834  /* RF: How much do we need to attenuate the RF pulses in scan. */
835  double my_xmtaddScan = -200 * log10(maxB1[L_SCAN] / maxB1Seq) + getCoilAtten();
836  if (my_xmtaddScan > cfdbmax) {
837  extraScale = (float) pow(10.0, (cfdbmax - my_xmtaddScan) / 200.0); /* N.B.: 'extraScale' is declared as CV in Prescan.e */
838  my_xmtaddScan = cfdbmax;
839  } else {
840  extraScale = 1.0;
841  }
842 
843  /* RF: Scale the rfpulse amplitudes */
844  status = setScale(L_SCAN, RF_FREE, rfpulse, maxB1[L_SCAN], extraScale);
845  if (status != SUCCESS) {
846  return ks_error("%s: setScale failed", __FUNCTION__);
847  }
848 
849  /* fill entry_point_table */
850  status = entrytabinit(entry_point_table, (int)ENTRY_POINT_MAX);
851  if (status != SUCCESS) {
852  return ks_error("%s: entrytabinit() failed", __FUNCTION__);
853  }
854  strcpy( entry_point_table[L_SCAN].epname, "scan");
855  entry_point_table[L_SCAN].epxmtadd = (short)rint( (double) my_xmtaddScan);
856  entry_point_table[L_SCAN].epstartrec = rhdab0s;
857  entry_point_table[L_SCAN].ependrec = rhdab0e;
858 #if EPIC_RELEASE < 29
859  entry_point_table[L_SCAN].epfastrec = 0;
860 #endif
861  entry_point_table[L_APS2] = entry_point_table[L_MPS2] = entry_point_table[L_SCAN];
862  strcpy(entry_point_table[L_APS2].epname, "aps2");
863  strcpy(entry_point_table[L_MPS2].epname, "mps2");
864 
865  /* Prescan: Final RF scaling of the Prescan entries, using the maxB1[] and maxB1Seq values computed above */
866 
867  /* prevent further addition of new sequence modules */
869 
870  /* Flag each sequence module that RF scaling has been done */
871  for (i = 0; i < seqcollection->numseq; i++) {
873  }
874 
875  return SUCCESS;
876 
877 } /* GEReq_eval_rfscaling() */
#define KS_MAXUNIQUE_RF
Definition: KSFoundation.h:255
RF_PULSE rfpulse[RF_FREE]
Definition: grad_rf_empty.h:55
#define MAX_ENTRY_POINTS
Definition: GERequired.e:146
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
int rfscalingdone
Definition: KSFoundation.h:1231
int mode
Definition: KSFoundation.h:1265
KS_SEQ_CONTROL * seqctrlptr[KS_MAXUNIQUE_SEQUENCES]
Definition: KSFoundation.h:1268
float maxB1Seq
Definition: GERequired.e:303
#define KS_RAISE(status)
Definition: KSFoundation.h:190
float maxB1[MAX_ENTRY_POINTS]
Definition: GERequired.e:303
KS_SEQ_COLLECTION seqcollection
Definition: ksepi.e:82
Definition: KSFoundation.h:2358
int numseq
Definition: KSFoundation.h:1264
STATUS ks_eval_seqcollection2rfpulse(RF_PULSE *rfpulse, KS_SEQ_COLLECTION *seqcollection)
(Internal use) Sets up GE&#39;s rfpulse[] array from the contents of a KS_SEQ_COLLECTION struct...
Definition: KSFoundation_host.c:6011

◆ GEReq_eval_checkTR_SAR_calcs()

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


2024 UPDATE: THE NEW HEATING MODEL IN KSFOUNDATION (2024) USES ks_eval_hwlimit() INSTEAD OF GEReq_eval_checkTR_SAR()

AND ksinv_eval_checkTR_SAR(), AFTER WHICH THIS FUNCTION IS CALLED TO UPDATE THE UI WITH SAR VALUES.

This function is called to check that the sequence modules played out in the slice loop sum up to the specified TR (optr) accounting for SAR/heating limits. Moreover, the SAR values are updated in the UI, and the CV ks_sarcheckdone is set to TRUE. This CV is set to FALSE in GEReq_cvinit() and check whether it is TRUE in GEReq_predownload() to make sure SAR calculation have been performed before scanning.

Parameters
[in,out]seqcollectionPointer to the KS_SEQ_COLLECTION struct holding all sequence modules
[in]intended_timeUsually repetition time (optr), should correspond to the intended time to play the corresponding number of sequence instances now set in seqcollection[]->seqctrl.ninst
Return values
STATUSSUCCESS or FAILURE
902  {
903  KS_SAR sar;
904  int duration_withinlimits;
905  s64 nettime;
906  STATUS status;
907 
908  /* Print out the sequence collection time table. In simulation it appears in the WTools main window */
909 #ifdef PSD_HW
910  FILE *fp = fopen("/usr/g/mrraw/seqcollection.txt", "w");
912  fclose(fp);
913 #else
915 #endif
916 
917  /*
918  The duration based on the sequence collection struct, which is the product .nseqinstances and .duration fields in each sequence
919  modules, summed over all sequence modules.
920  The .nseqinstances field becomes > 0 by the call to: GEReq_eval_TR()->ks_eval_mintr()->play_loop()->ks_scan_playsequence()
921  The .duration field is initially set to .min_duration by GEReq_eval_TR()->ks_eval_seqcollection_durations_atleastminimum(), but the
922  .duration field of at least one sequence module should have been set larger than its .min_duration based on the amount of
923  timetoadd_perTR returned by GEReq_eval_TR() */
925  if (nettime <= 0) {
926  return ks_error("%s: Nettime = %lld", __FUNCTION__, nettime);
927  }
928 
929  /* duration_withinlimits = nettime + grad/RF SAR/heat penalty time */
930  duration_withinlimits = ks_eval_rflimits(&sar, seqcollection);
931  if (duration_withinlimits == KS_NOTSET) {
932  return FAILURE;
933  }
934 
935  /* Make sure the global RF pulse array rfpulse[] is updated with the contents of the RF pulses in the sequence modules.
936  This also includes resetting all .activity fields to zero for the first KS_MAXUNIQUE_RF elements in rfpulse[] */
938  KS_RAISE(status);
939 
940 
941  /* report to UI */
942  piasar = (float) sar.average;
943  picasar = (float) sar.coil;
944  pipsar = (float) sar.peak;
945  pib1rms = (float) sar.b1rms;
946 
947  if (existcv(opslquant) == FALSE) {
948  /* if #slices has not been set yet, hold on complaining */
949  return SUCCESS;
950  }
951 
952  if (nettime < duration_withinlimits) {
953  return ks_error("%s: Duration of seq. modules (" S64_FMT ") < grad/rf limits (%d)", __FUNCTION__,
954  nettime, duration_withinlimits);
955  }
956 
957  double rel_timing_error = 0;
958  if (intended_time > 0 && nettime > 0) {
959  rel_timing_error = ((double) (intended_time - nettime)) / ((double) nettime);
960  }
961 
962  /* Any timing error is recorded in ks_debug.txt */
963  if (fabs(rel_timing_error) > 0) {
964  ks_dbg("%s: relative timing error %g. intended_time = %lld nettime = %lld", __FUNCTION__, rel_timing_error, intended_time, nettime);
965  }
966 
967  /* Timing errors > 0.01 percent is reported to the UI */
968  if (-rel_timing_error > MAX_SEQMODULES_DURATION_DEVIATION_FRACTION) { /* intended_time smaller than nettime */
969  /* small excess in nettime is expected due to roundups of .duration to nearest 4us, but we cannot accept too much */
970  return ks_error("%s: Duration of seq. modules (" S64_FMT ") " S64_FMT " us too long", __FUNCTION__,
971  nettime, (nettime - intended_time));
972  }
973  if (rel_timing_error > MAX_SEQMODULES_DURATION_DEVIATION_FRACTION) { /* intended_time larger than nettime */
974  return ks_error("%s: Duration of seq. modules (" S64_FMT ") " S64_FMT " us too short", __FUNCTION__,
975  nettime, (intended_time - nettime));
976  }
977 
978 
979 
980 #if EPIC_RELEASE >= 27
981  status = setupPowerMonitor(&entry_point_table[L_SCAN], sar.average);
982 #else
983  status = setupPowerMonitor(&entry_point_table[L_SCAN], L_SCAN, RF_FREE, rfpulse,
984  nettime, sar.average, sar.coil, sar.peak);
985 #endif
986  if (status != SUCCESS) {
987  return ks_error("%s: setupPowerMonitor failed", __FUNCTION__);
988  }
989 
990  /* prevent further addition of new sequence modules */
992 
993 
994  /* Flag that SAR check has been done */
995  ks_sarcheckdone = TRUE;
996 
997  return SUCCESS;
998 
999 } /* GEReq_eval_checkTR_SAR_calcs() */
double b1rms
Definition: KSFoundation.h:1285
RF_PULSE rfpulse[RF_FREE]
Definition: grad_rf_empty.h:55
#define KS_NOTSET
Definition: KSFoundation.h:115
#define MAX_SEQMODULES_DURATION_DEVIATION_FRACTION
Definition: GERequired.e:152
double average
Definition: KSFoundation.h:1282
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
double coil
Definition: KSFoundation.h:1283
void ks_print_seqcollection(KS_SEQ_COLLECTION *seqcollection, FILE *fp)
Print out the duration of each sequence module in the sequence collection to a file pointerBesides pr...
Definition: KSFoundation_host.c:6620
int mode
Definition: KSFoundation.h:1265
Struct to keep SAR parameters together. Used in ks_eval_rflimits() and GEReq_eval_checkTR_SAR_calcs()...
Definition: KSFoundation.h:1281
#define KS_RAISE(status)
Definition: KSFoundation.h:190
int ks_eval_rflimits(KS_SAR *sar, KS_SEQ_COLLECTION *seqcollection)
Returns the time required to play out a certain number of sequence modules over some interval...
Definition: KSFoundation_host.c:5703
int ks_sarcheckdone
Definition: GERequired.e:243
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
Definition: KSFoundation.h:2358
double peak
Definition: KSFoundation.h:1284
s64 ks_eval_seqcollection_gettotalduration(KS_SEQ_COLLECTION *seqcollection)
Returns the total duration of the sequence collection
Definition: KSFoundation_host.c:5965
STATUS ks_eval_seqcollection2rfpulse(RF_PULSE *rfpulse, KS_SEQ_COLLECTION *seqcollection)
(Internal use) Sets up GE&#39;s rfpulse[] array from the contents of a KS_SEQ_COLLECTION struct...
Definition: KSFoundation_host.c:6011

◆ GEReq_eval_checkTR_SAR()

STATUS GEReq_eval_checkTR_SAR ( KS_SEQ_COLLECTION seqcollection,
int  nslices,
int(*)(int, int, void **)  play_loop,
int  nargs,
void **  args 
)

Runs the slice loop and validates TR and SAR/hardware limits


2024 UPDATE: THIS FUNCTION IS ONLY USED BY KSGRE_TUTORIAL.E AND DEPCREATED PSDS.

THE NEW PSDS USE KSSCAN_LOOP_CONTROL CONTAINING KS_PHASEENCODING_PLAN AND KS_SLICETIMING FOR THE SCAN LOOP.

This function first makes sure that the .nseqinstances field for each sequence module in the sequence collection corresponds to the number of times played out in the sequence's sliceloop function.

In simulation (WTools), ks_print_seqcollection() will print out a table of the sequence modules in the sequence collection in the WToolsMgd window.

Finally, GEReq_eval_checkTR_SAR_calcs() is called to check that the TR is correct and within SAR/hardware limits.

N.B.: For inversion sequences, ksinv_eval_checkTR_SAR() is used to do the same thing, with the difference that ksinv_scan_sliceloop() is used instead.

Parameters
[in]seqcollectionPointer to the KS_SEQ_COLLECTION struct holding all sequence modules
[in]nslicesNumber of slices in TR
[in]play_loopFunction pointer to (the wrapper function to) the sliceloop function
[in]nargsNumber of extra input arguments to the sliceloop wrapper function.
[in]argsVoid pointer array pointing to the variables containing the actual values needed for the sliceloop function
Return values
STATUSSUCCESS or FAILURE
1034  {
1035 
1036  if (seqcollection == NULL || seqcollection->numseq == 0) {
1037  return ks_error("%s: Please add pulse sequence modules to the sequence collection before calling this function", __FUNCTION__);
1038  }
1039 
1040  /* set all `seqctrl.nseqinstances` to 0 */
1042  play_loop(nslices, nargs, args); /* => seqctrl.nseqinstances = # times each seq. module has been played out */
1043 
1045 
1046 } /* GEReq_eval_checkTR_SAR() */
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
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
int numseq
Definition: KSFoundation.h:1264

◆ GEReq_predownload_store_sliceplan()

STATUS GEReq_predownload_store_sliceplan ( KS_SLICE_PLAN  slice_plan)

Sets mandatory global GE arrays for data acquisition

The following global GE arrays are set based on slperpass (arg 1) and global op** variables:

  • data_acq_order[]: Critical for scanning
  • rsp_info[]: Copied from scan_info[] (the graphically prescibed slices), for conformance. Is a temporally sorted version of scan_info[] with integer rotation matrices. Not needed for scanning.
  • rsptrigger[]: Set to TRIG_INTERN for now.

data_acq_order[] is only available on HOST, why this function also copies data_acq_order[] to ks_data_acq_order[], which is an ipgexport array accessible on both HOST and TGT. This can be used by ks_scan_getsliceloc() to be independent on rsp_info[] during scan.

The slice plan is stored as a text file ("ks_sliceplan.txt") in the current directory in simulation and in /usr/g/mrraw on the MR scanner by calling ks_print_sliceplan().

Parameters
[in]slice_planThe current slice plan (KS_SLICE_PLAN) set up for the sequence (see ks_calc_sliceplan())
Return values
STATUSSUCCESS or FAILURE
1072  {
1073  int i, j, time;
1074 
1075  if (slice_plan.npasses == 0) {
1076  return KS_THROW("#acqs (.npasses) cannot be 0");
1077  }
1078 
1079  if (CEIL_DIV(slice_plan.nslices, slice_plan.nslices_per_pass) != slice_plan.npasses) {
1080  return KS_THROW("inconsistent slice plan - #acqs");
1081  }
1082 
1083  if (!KS_3D_SELECTED && slice_plan.nslices != exist(opslquant)) {
1084  return KS_THROW("inconsistent slice plan - #slices");
1085  }
1086 
1087  /* initialize rsp_info, rtsprot and rsptrigger */
1088  for (i = 0; i < DATA_ACQ_MAX; i++) {
1089  rsp_info[i].rsptloc = 0;
1090  rsp_info[i].rsprloc = 0;
1091  rsp_info[i].rspphasoff = 0;
1092  rsptrigger[i] = TRIG_INTERN;
1093  for (j = 0; j < 9; j++)
1094  rsprot[i][j] = 0;
1095  }
1096 
1097  /* copy to global data_acq_order, which must be correct for main sequence or scan will not start */
1098  for (i = 0; i < slice_plan.nslices; i++) {
1099  data_acq_order[i].slloc = slice_plan.acq_order[i].slloc;
1100  data_acq_order[i].slpass = slice_plan.acq_order[i].slpass;
1101  data_acq_order[i].sltime = slice_plan.acq_order[i].sltime;
1102  } /* for slice locations */
1103 
1104  for (i = slice_plan.nslices; i < SLICE_FACTOR*DATA_ACQ_MAX; i++) {
1105  data_acq_order[i].slloc = data_acq_order[i % slice_plan.nslices].slloc;
1106  data_acq_order[i].slpass = data_acq_order[i % slice_plan.nslices].slpass;
1107  data_acq_order[i].sltime = data_acq_order[i % slice_plan.nslices].sltime;
1108 #ifdef UNDEF
1109  data_acq_order[i].slloc = 0;
1110  data_acq_order[i].slpass = 0;
1111  data_acq_order[i].sltime = 0;
1112 #endif
1113  } /* for rest of data_acq_order */
1114 
1115  time = 0;
1116  for (i = 0; i < slice_plan.npasses; ++i) {
1117  for (j = 0; j < slice_plan.nslices_per_pass; ++j) {
1118  int slloc = ks_scan_getsliceloc(&slice_plan, i, j);
1119  if (slloc == KS_NOTSET) {continue;}
1120 
1121  rsp_info[time].rsptloc = scan_info[slloc].optloc;
1122  rsp_info[time].rsprloc = scan_info[slloc].oprloc;
1123  rsp_info[time].rspphasoff = scan_info[slloc].opphasoff;
1124 
1125  scale(&scan_info[slloc].oprot, &rsprot[time], 1, &loggrd, &phygrd, 0);
1126 
1127  /* Future: here we could change to a variable to support gating. TRIG_ECG, TRIG_AUX etc */
1128  rsptrigger[time] = TRIG_INTERN;
1129 
1130  ++time;
1131  }
1132  }
1133 
1134  /* Save acquisition table to disk for debugging */
1135  FILE* daqfp = ks_open_file_in_embed("sliceplan.txt", "w");
1136  ks_print_sliceplan(slice_plan, daqfp);
1137  fclose(daqfp);
1138 
1139  STATUS status = calcChecksumScanInfo(&chksum_scaninfo, scan_info, slice_plan.nslices, psdcrucial_debug);
1140  if (status != SUCCESS) {
1141  epic_error(1, "GEReq...sliceplan(): PSD data integrity violation detected in PSD",
1142  EM_PSD_PSDCRUCIAL_DATA_FAILURE, EE_ARGS(1), SYSLOG_ARG);
1143  return status;
1144  }
1145 
1146  /* set GE acqs and slquant1 CVs for look and feel */
1147  _slquant1.fixedflag = 0;
1148  _acqs.fixedflag = 0;
1149  slquant1 = slice_plan.nslices_per_pass;
1150  acqs = slice_plan.npasses;
1151  /* prescan */
1152  picalmode = 0;
1153  pislquant = slquant1;
1154 
1155  return SUCCESS;
1156 
1157 } /* GEReq_predownload_store_sliceplan() */
DATA_ACQ_ORDER acq_order[SLICE_FACTOR *DATA_ACQ_MAX]
Definition: KSFoundation.h:1321
#define KS_NOTSET
Definition: KSFoundation.h:115
void ks_print_sliceplan(const KS_SLICE_PLAN slice_plan, FILE *fp)
Writes a KS_SLICE_PLAN to a file pointer
Definition: KSFoundation_host.c:6639
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
PHYS_GRAD phygrd
int nslices_per_pass
Definition: KSFoundation.h:1320
int npasses
Definition: KSFoundation.h:1319
LOG_GRAD loggrd
SCAN_INFO scan_info[]
long rsprot[TRIG_ROT_MAX][9]
STATUS scale(FLOAT(*inrotmat)[9], long(*outrotmat)[9], INT slquant, LOG_GRAD *lgrad, PHYS_GRAD *pgrad, INT contdebug)
int nslices
Definition: KSFoundation.h:1318
FILE * ks_open_file_in_embed(const char *fname, const char *write_mode)
ADDTITLEHERE
Definition: KSFoundation_common.c:4715
int ks_scan_getsliceloc(const KS_SLICE_PLAN *slice_plan, int passindx, int sltimeinpass)
Returns the spatially sorted slice index from a DATA_ACQ_ORDER struct array
Definition: KSFoundation_tgt.c:1214
#define KS_THROW(format,...)
Definition: KSFoundation.h:181

◆ GEReq_predownload_store_sliceplan_sms()

STATUS GEReq_predownload_store_sliceplan_sms ( const KS_SLICE_PLAN  slice_plan,
int  sms_factor 
)
1162  {
1163  int i, j, time;
1164 
1165  if (slice_plan.npasses == 0) {
1166  return ks_error("%s: #acqs (.npasses) cannot be 0", __FUNCTION__);
1167  }
1168 
1169  if (CEIL_DIV(slice_plan.nslices, slice_plan.nslices_per_pass) != slice_plan.npasses) {
1170  return ks_error("%s: inconsistent slice plan - #acqs", __FUNCTION__);
1171  }
1172 
1173  if (!KS_3D_SELECTED && slice_plan.nslices * sms_factor != exist(opslquant)) {
1174  return ks_error("%s: inconsistent slice plan - #slices", __FUNCTION__);
1175  }
1176 
1177  /* initialize rsp_info, rtsprot and rsptrigger */
1178  for (i = 0; i < DATA_ACQ_MAX; i++) {
1179  rsp_info[i].rsptloc = 0;
1180  rsp_info[i].rsprloc = 0;
1181  rsp_info[i].rspphasoff = 0;
1182  rsptrigger[i] = TRIG_INTERN;
1183  for (j = 0; j < 9; j++)
1184  rsprot[i][j] = 0;
1185  }
1186 
1187  /* copy to global data_acq_order, which must be correct for main sequence or scan will not start */
1188  for (i = 0; i < slice_plan.nslices; i++) {
1189  data_acq_order[i].slloc = slice_plan.acq_order[i].slloc;
1190  data_acq_order[i].slpass = slice_plan.acq_order[i].slpass;
1191  data_acq_order[i].sltime = slice_plan.acq_order[i].sltime;
1192  } /* for slice locations */
1193 
1194  for (i = slice_plan.nslices; i < SLICE_FACTOR*DATA_ACQ_MAX; i++) {
1195  data_acq_order[i].slloc = i;
1196  data_acq_order[i].slpass = data_acq_order[i % slice_plan.nslices].slpass;
1197  data_acq_order[i].sltime = data_acq_order[i % slice_plan.nslices].sltime;
1198  } /* for rest of data_acq_order */
1199 
1200  time = 0;
1201  for (i = 0; i < slice_plan.npasses; ++i) {
1202  for (j = 0; j < slice_plan.nslices_per_pass; ++j) {
1203  int slloc = ks_scan_getsliceloc(&slice_plan, i, j);
1204  if (slloc == KS_NOTSET) {continue;}
1205 
1206  rsp_info[time].rsptloc = scan_info[slloc].optloc;
1207  rsp_info[time].rsprloc = scan_info[slloc].oprloc;
1208  rsp_info[time].rspphasoff = scan_info[slloc].opphasoff;
1209 
1210  scale(&scan_info[slloc].oprot, &rsprot[time], 1, &loggrd, &phygrd, 0);
1211 
1212  /* Future: here we could change to a variable to support gating. TRIG_ECG, TRIG_AUX etc */
1213  rsptrigger[time] = TRIG_INTERN;
1214 
1215  ++time;
1216  }
1217  }
1218 
1219  /* Save acquisition table to disk for debugging */
1220  FILE* daqfp = ks_open_file_in_embed("sliceplan.txt", "w");
1221  ks_print_sliceplan(slice_plan, daqfp);
1222  fclose(daqfp);
1223 
1224  STATUS status = calcChecksumScanInfo(&chksum_scaninfo, scan_info, slice_plan.nslices*sms_factor, psdcrucial_debug);
1225  if (status != SUCCESS) {
1226  epic_error(1, "GEReq...sliceplan(): PSD data integrity violation detected in PSD",
1227  EM_PSD_PSDCRUCIAL_DATA_FAILURE, EE_ARGS(1), SYSLOG_ARG);
1228  return status;
1229  }
1230 
1231  /* set GE acqs and slquant1 CVs for look and feel */
1232  _slquant1.fixedflag = 0;
1233  _acqs.fixedflag = 0;
1234  slquant1 = slice_plan.nslices_per_pass;
1235  acqs = slice_plan.npasses;
1236  /* prescan */
1237  picalmode = 0;
1238  pislquant = slquant1;
1239 
1240  return SUCCESS;
1241 
1242 } /* GEReq_predownload_store_sliceplan_sms() */
DATA_ACQ_ORDER acq_order[SLICE_FACTOR *DATA_ACQ_MAX]
Definition: KSFoundation.h:1321
#define KS_NOTSET
Definition: KSFoundation.h:115
void ks_print_sliceplan(const KS_SLICE_PLAN slice_plan, FILE *fp)
Writes a KS_SLICE_PLAN to a file pointer
Definition: KSFoundation_host.c:6639
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
PHYS_GRAD phygrd
int nslices_per_pass
Definition: KSFoundation.h:1320
int npasses
Definition: KSFoundation.h:1319
LOG_GRAD loggrd
SCAN_INFO scan_info[]
long rsprot[TRIG_ROT_MAX][9]
STATUS scale(FLOAT(*inrotmat)[9], long(*outrotmat)[9], INT slquant, LOG_GRAD *lgrad, PHYS_GRAD *pgrad, INT contdebug)
int nslices
Definition: KSFoundation.h:1318
FILE * ks_open_file_in_embed(const char *fname, const char *write_mode)
ADDTITLEHERE
Definition: KSFoundation_common.c:4715
int ks_scan_getsliceloc(const KS_SLICE_PLAN *slice_plan, int passindx, int sltimeinpass)
Returns the spatially sorted slice index from a DATA_ACQ_ORDER struct array
Definition: KSFoundation_tgt.c:1214

◆ GEReq_predownload_store_sliceplan3D()

STATUS GEReq_predownload_store_sliceplan3D ( int  slices_in_slab,
int  slabs 
)

Sets mandatory global GE arrays for data acquisition (3D imaging)

The following global GE arrays are set based on slperpass (arg 1) and global op** variables:

  • data_acq_order[]: Critical for scanning
  • rsp_info[]: Copied from scan_info[] (the graphically prescibed slices), for conformance. Is a temporally sorted version of scan_info[] with integer rotation matrices. Not needed for scanning.
  • rsptrigger[]: Set to TRIG_INTERN for now.

data_acq_order[] is only available on HOST, why this function also copies data_acq_order[] to ks_data_acq_order[], which is an ipgexport array accessible on both HOST and TGT. This can be used by ks_scan_getsliceloc() to be independent on rsp_info[] during scan.

GEReq_predownload_store_sliceplan3D() has different input args compared to the 2D version. Here, a temporary slice plan is created based on slices_in_slab and slabs in order to create the proper content of data_acq_order[]. Note that it wouldn't have worked to pass ks_slice_plan for 3D. This is because we need a ks_slice_plan that is consistent with RF excitations for 2D, 3D, 3DMS in each sequence's looping structure in scan. For 3D, this very ks_slice_plan can then not also create the proper data_acq_order array here. This is why we pass in slices_in_slab and slabs instead and create e temp slice plan solely for the purpose of data_acq_order.

Parameters
[in]slices_in_slabNumber of slices in a slab
[in]slabsNumber slabs
Return values
STATUSSUCCESS or FAILURE
1275  {
1276  KS_SLICE_PLAN slice_plan;
1277 
1278  /* TODO: unclear for 3D MS, inteleaved and sequential */
1279  ks_calc_sliceplan_interleaved(&slice_plan, slices_in_slab * slabs, slices_in_slab, 1);
1280 
1281  return GEReq_predownload_store_sliceplan(slice_plan);
1282 
1283 } /* GEReq_predownload_store_sliceplan3D() */
STATUS GEReq_predownload_store_sliceplan(KS_SLICE_PLAN slice_plan)
Sets mandatory global GE arrays for data acquisition
Definition: GERequired.e:1072
Struct holding all information about slice locations and aquisition order
Definition: KSFoundation.h:1317
STATUS ks_calc_sliceplan_interleaved(KS_SLICE_PLAN *slice_plan, int nslices, int slperpass, int inpass_interleaves)
Calculates the data acquisition order for custom interleaved 2D scans using one or more passes...
Definition: KSFoundation_host.c:6304

◆ GEReq_predownload_setfilter_or_find_equivalent()

STATUS GEReq_predownload_setfilter_or_find_equivalent ( FILTER_INFO *  myfilter,
FILTER_BLOCK_TYPE  type 
)

Assigns a global filter slot for a main sequence

This function must be called in predownload() after GE's initfilter() function, which resets all filter slots for scan and prescan entry points. The initfilter() function is called in GEReq_cvinit().

Given the FILTER_INFO of the acquisition window for the main pulse sequence (arg 1), this function assigns a new slot number (that matches one of the hardware slots in the data receive chain.

The .epfilter and .epprexres of GE's global struct array entry_point_table[] is also set.

Parameters
[in]myfilterPointer to FILTER_INFO struct (.filt field in KS_READ)
[in]typeChoose between SCAN & PRESCAN
Return values
STATUSSUCCESS or FAILURE
1306  {
1307  int i;
1308  /* PSD_FILTER_GEN psd_filt_spec --> setfilter.cpp */
1309 
1310  /* Filter has been set before, inititlization value for filter_slot = -1 (KS_NOTSET) in KS_INIT_FINFO */
1311  if (myfilter->fslot != KS_NOTSET){
1312  return SUCCESS;
1313  }
1314 
1315  for (i=0; i < PSD_FILTER_MAX; i++){
1316  if (psd_filt_spec[i].filter_slot == -1){
1317  /* psd_filt_spec is initialized with -1 for all slots, slots are filled in order, -1 indicates this one and all subsequent are unused yet */
1318  break;
1319  }
1320 
1321  if (psd_filt_spec[i].outputs == myfilter->outputs && (int) psd_filt_spec[i].filfrq*1000 == (int) myfilter->bw*1000){
1322  myfilter->fslot = i;
1323  /*ks_dbg("Existing filter slot %d found for outputs = %d, bw = %.1f", i, myfilter->outputs, myfilter->bw);*/
1324  return SUCCESS;
1325  }
1326  }
1327 
1328  if (i >= PSD_FILTER_MAX){
1329  ks_error("Requested filter slot %d (zero indexed) > PSD_FILTER_MAX (%d); outputs = %d, bw = %.1f ...", i, PSD_FILTER_MAX, myfilter->outputs, myfilter->bw);
1330  return FAILURE;
1331  }
1332 
1333  if (setfilter( myfilter, type) == FAILURE) {
1334  epic_error(use_ermes, "%s failed", EM_PSD_SUPPORT_FAILURE,
1335  EE_ARGS(1), STRING_ARG, "setfilter");
1336  return FAILURE;
1337  }
1338 
1339  /*ks_dbg("New filter slot %d taken for outputs = %d, bw = %.1f", myfilter->fslot , myfilter->outputs, myfilter->bw);*/
1340 
1341  return SUCCESS;
1342 
1343 } /* GEReq_predownload_setfilter_or_find_equivalent() */
#define KS_NOTSET
Definition: KSFoundation.h:115
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT

◆ GEReq_get_num_used_slots()

int GEReq_get_num_used_slots ( )
1348  {
1349  int i;
1350  for (i=0; i < PSD_FILTER_MAX; i++){
1351  if (psd_filt_spec[i].filter_slot == -1){
1352  /* psd_filt_spec is initialized with -1 for all slots, slots are filled in order, -1 indicates this one and all subsequent are unused yet */
1353  break;
1354  }
1355  }
1356  return i;
1357 
1358 } /* GEReq_get_num_used_slots() */

◆ GEReq_get_maxsize_finfo()

PSD_FILTER_GEN GEReq_get_maxsize_finfo ( int  n_prescan_slots)
1363  {
1364  int i;
1365  PSD_FILTER_GEN max_length_finfo = {0};
1366  max_length_finfo.outputs = 0;
1367  for (i = n_prescan_slots; i < PSD_FILTER_MAX; i++) {
1368  if(psd_filt_spec[i].outputs > max_length_finfo.outputs) {
1369  max_length_finfo = psd_filt_spec[i];
1370  }
1371  if (psd_filt_spec[i].filter_slot == -1){
1372  break;
1373  }
1374  }
1375  return max_length_finfo;
1376 
1377 } /* GEReq_get_maxsize_finfo() */

◆ GEReq_predownload_setfilter()

STATUS GEReq_predownload_setfilter ( FILTER_INFO *  filt)
1382  {
1383 
1384  setfilter(filt, SCAN);
1385 
1386  entry_point_table[L_SCAN].epfilter = (unsigned char) filt->fslot;
1387  entry_point_table[L_SCAN].epprexres = filt->outputs;
1388 
1389  return SUCCESS;
1390 
1391 } /* GEReq_predownload_setfilter() */

◆ GEReq_echotrain_setfilters()

STATUS GEReq_echotrain_setfilters ( KS_ECHOTRAIN *const  echotrain)
1396  {
1397  STATUS status;
1398  int i, object_index;
1399  for (i = 0; i < echotrain->numreadouts; i++) {
1400  object_index = echotrain->controls[i].pg.object_index;
1401  if (echotrain->controls[i].pg.read_type == KS_READ_TRAP) {
1402  status = GEReq_predownload_setfilter_or_find_equivalent(&echotrain->readtraps[object_index].acq.filt, SCAN);
1403  } else {
1404  status = GEReq_predownload_setfilter_or_find_equivalent(&echotrain->readwaves[object_index].acq.filt, SCAN);
1405  }
1406  KS_RAISE(status);
1407  }
1408  return SUCCESS;
1409 
1410 } /* GEReq_echotrain_setfilters() */
KS_READTRAP readtraps[KS_ECHOTRAIN_MAX_TRAPS]
Definition: KSFoundation.h:2016
KS_READWAVE readwaves[KS_ECHOTRAIN_MAX_WAVES]
Definition: KSFoundation.h:2017
int object_index
Definition: KSFoundation.h:1985
KS_READCONTROL_PULSEGEN pg
Definition: KSFoundation.h:2001
STATUS GEReq_predownload_setfilter_or_find_equivalent(FILTER_INFO *myfilter, FILTER_BLOCK_TYPE type)
Assigns a global filter slot for a main sequence
Definition: GERequired.e:1306
KS_READ_TYPE read_type
Definition: KSFoundation.h:1984
Definition: KSFoundation.h:1959
#define KS_RAISE(status)
Definition: KSFoundation.h:190
FILTER_INFO filt
Definition: KSFoundation.h:843
int numreadouts
Definition: KSFoundation.h:2020
KS_READ acq
Definition: KSFoundation.h:1549
KS_READ acq
Definition: KSFoundation.h:1606
KS_READCONTROL controls[KS_MAXUNIQUE_READ]
Definition: KSFoundation.h:2015

◆ GEReq_predownload_minimize_ps_filter_slots()

STATUS GEReq_predownload_minimize_ps_filter_slots ( )
1416  {
1417  STATUS status;
1418 
1419  echo1cfl.fslot = KS_NOTSET; /*GE filter fslot is uninitialized, GEReq_predownload_setfilter_or_find_equivalent returns early if fslot is not -1 */
1420  status = GEReq_predownload_setfilter_or_find_equivalent(&echo1cfl, PRESCAN);
1421  KS_RAISE(status);
1422  filter_cfl_fid = echo1cfl.fslot;
1423 
1424  echo1rcvn.fslot = KS_NOTSET;
1425  status = GEReq_predownload_setfilter_or_find_equivalent(&echo1rcvn, PRESCAN);
1426  KS_RAISE(status);
1427  filter_rcvn_fid = echo1rcvn.fslot;
1428 
1429  echo1cfh.fslot = KS_NOTSET;
1430  status = GEReq_predownload_setfilter_or_find_equivalent(&echo1cfh, PRESCAN);
1431  KS_RAISE(status);
1432  filter_cfh_fid = echo1cfh.fslot;
1433 
1434  echo1mps1_filt.fslot = KS_NOTSET;
1435  status = GEReq_predownload_setfilter_or_find_equivalent(&echo1mps1_filt, PRESCAN);
1436  KS_RAISE(status);
1437  filter_echo1mps1 = echo1mps1_filt.fslot;
1438 
1439  echo1ftg_filt.fslot = KS_NOTSET;
1440  status = GEReq_predownload_setfilter_or_find_equivalent(&echo1ftg_filt, PRESCAN);
1441  KS_RAISE(status);
1442  filter_echo1ftg = echo1ftg_filt.fslot;
1443  filter_echo2ftg = filter_echo1ftg; /* from prescan.e */
1444 
1445  echo1xtg_filt.fslot = KS_NOTSET;
1446  status = GEReq_predownload_setfilter_or_find_equivalent(&echo1xtg_filt, PRESCAN);
1447  KS_RAISE(status);
1448  filter_echo1xtg = echo1xtg_filt.fslot;
1449 
1450  echo1as_filt.fslot = KS_NOTSET;
1451  status = GEReq_predownload_setfilter_or_find_equivalent(&echo1as_filt, PRESCAN);
1452  KS_RAISE(status);
1453  filter_echo1as = echo1as_filt.fslot;
1454 
1455  echo1rs_filt.fslot = KS_NOTSET;
1456  status = GEReq_predownload_setfilter_or_find_equivalent(&echo1rs_filt, PRESCAN);
1457  KS_RAISE(status);
1458  filter_echo1rs = echo1rs_filt.fslot;
1459 
1460  echo1dtg_filt.fslot = KS_NOTSET;
1461  status = GEReq_predownload_setfilter_or_find_equivalent(&echo1dtg_filt, PRESCAN);
1462  KS_RAISE(status);
1463  filter_echo1dtg = echo1dtg_filt.fslot;
1464 
1465 #if EPIC_RELEASE > 26
1466  echo1cal_filt.fslot = KS_NOTSET;
1467  status = GEReq_predownload_setfilter_or_find_equivalent(&echo1cal_filt, PRESCAN);
1468  KS_RAISE(status);
1469  filter_echo1cal = echo1cal_filt.fslot;
1470 
1471  echo1coil_filt.fslot = KS_NOTSET;
1472  status = GEReq_predownload_setfilter_or_find_equivalent(&echo1coil_filt, PRESCAN);
1473  KS_RAISE(status);
1474  filter_echo1coil = echo1coil_filt.fslot;
1475 #endif
1476 
1477  if(psddebugcode) {
1478  dump_runtime_filter_info(psd_filt_spec);
1479  }
1480 
1481  return SUCCESS;
1482 
1483 } /* GEReq_predownload_minimize_ps_filter_slots() */
#define KS_NOTSET
Definition: KSFoundation.h:115
STATUS GEReq_predownload_setfilter_or_find_equivalent(FILTER_INFO *myfilter, FILTER_BLOCK_TYPE type)
Assigns a global filter slot for a main sequence
Definition: GERequired.e:1306
#define KS_RAISE(status)
Definition: KSFoundation.h:190

◆ GEReq_setfilters()

STATUS GEReq_setfilters ( KS_SEQ_COLLECTION *const  seq_collection)
1488  {
1489  STATUS status;
1490  int i_seqctrlptr, i_reads;
1491 
1492  for (i_seqctrlptr = 0; i_seqctrlptr < seq_collection->numseq; i_seqctrlptr++) {
1493 
1494  KS_GRADRFCTRL* gradrf = &seq_collection->seqctrlptr[i_seqctrlptr]->gradrf;
1495 
1496  for (i_reads = 0; i_reads < gradrf->numacq; i_reads++) {
1497  FILTER_INFO* filt = &gradrf->readptr[i_reads]->filt;
1499  KS_RAISE(status);
1500  }
1501 
1502  }
1503  return SUCCESS;
1504 
1505 } /* GEReq_setfilters() */
KS_SEQ_CONTROL * seqctrlptr[KS_MAXUNIQUE_SEQUENCES]
Definition: KSFoundation.h:1268
STATUS GEReq_predownload_setfilter_or_find_equivalent(FILTER_INFO *myfilter, FILTER_BLOCK_TYPE type)
Assigns a global filter slot for a main sequence
Definition: GERequired.e:1306
KS_GRADRFCTRL gradrf
Definition: KSFoundation.h:1236
typedef struct that is a part of the KS_SEQ_CONTROL typedef struct, used internally to collect gradie...
Definition: KSFoundation.h:1054
#define KS_RAISE(status)
Definition: KSFoundation.h:190
FILTER_INFO filt
Definition: KSFoundation.h:843
KS_READ * readptr[KS_MAXUNIQUE_READ]
Definition: KSFoundation.h:1061
int numacq
Definition: KSFoundation.h:1062
int numseq
Definition: KSFoundation.h:1264

◆ GEReq_predownload_genVRGF()

STATUS GEReq_predownload_genVRGF ( const KS_READTRAP *const  readtrap)

Generates the vrgf.param file for rampsampling correction

When the .rampsampling field of a KS_READTRAP is set to 1, 1D gridding in the frequency encoding direction is necessary before FFT to obtain an equidistant k-space. GE's product reconstruction uses a file (vrgf.param) for this, which is generated by this function.

See also GEReq_predownload_setrecon_readphase(), which sets VRGF-specific global variables.

Parameters
[in]readtrap
Return values
STATUSSUCCESS or FAILURE
1523  {
1524  FILE *fpVRGF = NULL;
1525  float beta = 1.0;
1526  float alpha = 2.0 / (beta + 1.0);
1527 #ifdef SIM
1528  fpVRGF = fopen("./vrgf.param", "w");
1529 #else
1530  #if EPIC_RELEASE > 29
1531  fpVRGF = fopen("/srv/nfs/psd/var/psddata/vrgf.param", "w");
1532  #else
1533  fpVRGF = fopen("/usr/g/bin/vrgf.param", "w");
1534  #endif
1535 #endif
1536 
1537  if (fpVRGF == NULL) {
1538  return KS_THROW("Can't create vrgf.param");
1539  }
1540 
1541  /* based on: /ESE.../.../psdsupport/genVRGF.c */
1542 
1543  /* NOTE: The static file /usr/g/bin/vrgf.param2, i.e. with a trailing "2", containing the following
1544  must exist on the system in order for the executable /usr/g/bin/vrgf to generate vrgf.dat from
1545  the vrgf.param we are about to write:
1546  VRGFNORM= 1
1547  GAIN= 1.0
1548  VRGFWN= 1
1549  ALPHA= 0.46
1550  BETA= 1.0
1551  VRGFODS= 0.0
1552  VRGFCC= 0
1553  VRGFGS= 1
1554  VRGFSGG= 0
1555  VRGFBWF= -1.0
1556  */
1557 
1558 
1559  fprintf(fpVRGF, "VRGFIP= %d\n", readtrap->acq.filt.outputs);
1560  fprintf(fpVRGF, "VRGFOP= %d\n", readtrap->res);
1561  fprintf(fpVRGF, "PERIOD= %f\n", readtrap->acq.filt.tsp);
1562  fprintf(fpVRGF, "WAVE_CHOICE= %d\n", 1);
1563  fprintf(fpVRGF, "G1= %d\n", 1);
1564  fprintf(fpVRGF, "G2= %f\n", readtrap->grad.amp);
1565  fprintf(fpVRGF, "G3= %f\n", (readtrap->grad.plateautime / 2) / 1.0e6);
1566  fprintf(fpVRGF, "G4= %f\n", readtrap->grad.ramptime / 1.0e6);
1567  fprintf(fpVRGF, "G5= %f\n", alpha);
1568  fprintf(fpVRGF, "G6= %f\n", beta);
1569  fprintf(fpVRGF, "G7= %f\n", 0.0);
1570  fprintf(fpVRGF, "G8= %f\n", readtrap->acq.rbw * 1.0e3);
1571  fprintf(fpVRGF, "G9= %f\n", 0.0);
1572 
1573  if (fclose(fpVRGF) != 0) {
1574  return KS_THROW("Can't close vrgf.param");
1575  }
1576 
1577  return SUCCESS;
1578 
1579 } /* GEReq_predownload_genVRGF() */
int plateautime
Definition: KSFoundation.h:672
float rbw
Definition: KSFoundation.h:842
KS_TRAP grad
Definition: KSFoundation.h:1561
int res
Definition: KSFoundation.h:1552
float amp
Definition: KSFoundation.h:669
FILTER_INFO filt
Definition: KSFoundation.h:843
KS_READ acq
Definition: KSFoundation.h:1549
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
int ramptime
Definition: KSFoundation.h:671

◆ GEReq_predownload_genrowflip()

STATUS GEReq_predownload_genrowflip ( KS_EPI epi,
int  blipsign,
int  assetflag,
int  dorowflip 
)

Generates the rowflip.param file for KS_EPI

GE's reconstruction (and data dumping) of EPI data (where every other readout is negative) needs to know which k-space lines that have been acquired with a negative gradient to perform a row flip on these lines before proceeding with Pfile writing and FFT processing.

Parameters
[in]epiPointer to KS_EPI
[in]blipsignKS_EPI_POSBLIPS or KS_EPI_NEGBLIPS
[in]assetflagFlag for ASSET mode or not (0: off, 2: ASSET_SCAN (on))
[in]dorowflipIf 0, write just ones to let rowflipping process for Pfiles being executed without actual flipping
Return values
STATUSSUCCESS or FAILURE
1598  {
1599  FILE *rowflipfp = NULL;
1600  int i = 0;
1601  int j = 0;
1602  int kyview = 0;
1603  int view1st, viewskip;
1604  int readsign = 1;
1605  int rowskip, res;
1606 #ifdef SIM
1607  rowflipfp = fopen("./rowflip.param", "w");
1608 #else
1609  #if EPIC_RELEASE > 29
1610  rowflipfp = fopen("/srv/nfs/psd/var/psddata/rowflip.param", "w");
1611  #else
1612  rowflipfp = fopen("/usr/g/bin/rowflip.param", "w");
1613  #endif
1614 #endif
1615 
1616  if (rowflipfp == NULL) {
1617  ks_error("Can't create rowflip.param");
1618  }
1619 
1620 
1621  fprintf(rowflipfp, "# EPI recon control\n");
1622  fprintf(rowflipfp, "#\n");
1623  fprintf(rowflipfp, "# ky line number/flip operation\n");
1624  fprintf(rowflipfp, "%d %d\n", 0, 1);
1625 
1626  if (assetflag == ASSET_SCAN) {
1627  rowskip = 1;
1628  res = epi->blipphaser.res / epi->blipphaser.R;
1629  } else {
1630  rowskip = epi->blipphaser.R;
1631  res = epi->blipphaser.res;
1632  }
1633 
1634  for (i = 0; i < epi->etl; i++) {
1635  for (j = 0; j < rowskip; j++) {
1636  kyview = i * rowskip + j;
1637  readsign = (i % 2) ? -1 : 1;
1638  if (blipsign == KS_EPI_POSBLIPS && (epi->etl % 2 == 0)) {
1639  readsign *= -1;
1640  }
1641  fprintf(rowflipfp, "%d %d\n", kyview + 1, (dorowflip) ? readsign : 1);
1642  }
1643  }
1644  for (kyview = i * rowskip + j; kyview < res; kyview++)
1645  fprintf(rowflipfp, "%d %d\n", kyview + 1, 1);
1646 
1647  fprintf(rowflipfp, "#\n#\n#intleave 1stview skip gpol bpol gy1f rfpol tf nechoes init_echo_pol\n" );
1648 
1649  for (j = 0; j < rowskip; j++) {
1650  if (blipsign == KS_EPI_POSBLIPS && (epi->etl % 2 == 0)) {
1651  view1st = (assetflag == ASSET_SCAN) ? (epi->blipphaser.numlinestoacq - 1) : (epi->blipphaser.linetoacq[(epi->blipphaser.numlinestoacq - 1)] + j);
1652  viewskip = -rowskip;
1653  } else {
1654  view1st = (assetflag == ASSET_SCAN) ? 0 : (epi->blipphaser.linetoacq[0] + j);
1655  viewskip = rowskip;
1656  }
1657  fprintf(rowflipfp, "%d %d %d %d %d %d %d %d %d %d\n", j, view1st + 1, viewskip, 1, blipsign, 0 /* max int dephaser */, 1 /* rfpol*/, 0 /* tf */, epi->etl, 1);
1658  }
1659 
1660  fprintf(rowflipfp, "# esp (usec)\n");
1661  fprintf(rowflipfp, "%d \n", epi->read.grad.duration);
1662  fprintf(rowflipfp, "# tsp (usec)\n");
1663  fprintf(rowflipfp, "%f \n", epi->read.acq.filt.tsp);
1664  fprintf(rowflipfp, "# input samples\n");
1665  fprintf(rowflipfp, "%d \n", epi->read.acq.filt.outputs);
1666  fprintf(rowflipfp, "# readout amplitude (G/cm)\n");
1667  fprintf(rowflipfp, "%f \n", epi->read.grad.amp);
1668  fprintf(rowflipfp, "# Row FT size\n");
1669  fprintf(rowflipfp, "%d \n", epi->read.res);
1670  fprintf(rowflipfp, "# rhhnover \n");
1671  fprintf(rowflipfp, "%d \n", epi->blipphaser.nover);
1672  fprintf(rowflipfp, "# etl\n");
1673  fprintf(rowflipfp, "%d \n", epi->etl);
1674  fprintf(rowflipfp, "# number of interleaves\n");
1675  fprintf(rowflipfp, "%d \n", epi->blipphaser.R);
1676  fprintf(rowflipfp, "# low pass filter setting (kHz), or -1 for std. rcvr.\n");
1677  fprintf(rowflipfp, "%d \n", -1);
1678  fprintf(rowflipfp, "# total number of images\n");
1679  fprintf(rowflipfp, "%d \n", opslquant);
1680  fprintf(rowflipfp, "# end of file");
1681 
1682  fclose(rowflipfp);
1683 
1684  return SUCCESS;
1685 
1686 } /* GEReq_predownload_genrowflip() */
int R
Definition: KSFoundation.h:1723
int res
Definition: KSFoundation.h:1721
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
KS_PHASER blipphaser
Definition: KSFoundation.h:1937
int numlinestoacq
Definition: KSFoundation.h:1727
int linetoacq[KS_MAX_PHASEDYN]
Definition: KSFoundation.h:1728
KS_TRAP grad
Definition: KSFoundation.h:1561
int etl
Definition: KSFoundation.h:1941
int res
Definition: KSFoundation.h:1552
KS_READTRAP read
Definition: KSFoundation.h:1932
Definition: KSFoundation.h:2330
float amp
Definition: KSFoundation.h:669
int nover
Definition: KSFoundation.h:1722
FILTER_INFO filt
Definition: KSFoundation.h:843
KS_READ acq
Definition: KSFoundation.h:1549
int duration
Definition: KSFoundation.h:673

◆ GEReq_predownload_setrecon_writekacq()

STATUS GEReq_predownload_setrecon_writekacq ( const KS_READTRAP *const  readtrap,
const KS_PHASER *const  phaser,
const KS_PHASER *const  zphaser 
)

Writes a kacq_yz.txt.***** file for use with GE's product ARC recon

If phaser.R > 1, a file is written to disk with phase encoding steps in an ARC accelerated scan ("kacq_yz.txt.*****"). This function has been adapted from GE's ARC.e, but supports only 2D (i.e. 1D-acceleration)

Parameters
[in]readtrapPointer to readout trapezoid. Used to determine k-space peak along kx
[in]phaserPointer to phase encoding object (KS_PHASER) with acceleration
[in]zphaserPointer to z phase encoding object (KS_PHASER) with acceleration. NULL for 2D
Return values
STATUSSUCCESS or FAILURE
1710  {
1711 
1712  FILE *fp;
1713  CHAR kacqFilename[BUFSIZ];
1714  int view;
1715  int arc_kx_peak_pos = 0; /* sample point units */
1716  /* int arc_ky_peak_pos = -1; */
1717  const CHAR kacqArcFilename[BUFSIZ] = "kacq_yz.txt";
1718  int num_echoes = 1; /* we don't understand what a value > 1 would mean. cf. ARC.e */
1719  int echo_index, slice;
1720  int numzencodes = (zphaser != NULL) ? zphaser->numlinestoacq : 1;
1721 
1722 #ifdef PSD_HW
1723  #if EPIC_RELEASE > 29
1724  const CHAR kacqPath[BUFSIZ] = "/srv/nfs/psd/var/psddata/";
1725  #else
1726  const CHAR kacqPath[BUFSIZ] = "/usr/g/psddata/";
1727  #endif
1728  sprintf(kacqFilename, "%s%s.%d", kacqPath, kacqArcFilename, rhkacq_uid);
1729 #else
1730  const CHAR kacqPath[BUFSIZ] = "./";
1731  sprintf(kacqFilename, "%s%s", kacqPath, kacqArcFilename);
1732 #endif
1733 
1734  fp = fopen(kacqFilename, "w");
1735 
1736  /* position of k-space center in sample points along kx
1737  time2center - acqdelay is the time in [us] from start of acq window to the center of k-space
1738  acq.filt.tsp is the time in [us] for one sample point (with or without ramp sampling */
1739  arc_kx_peak_pos = (readtrap->time2center - readtrap->acqdelay) / readtrap->acq.filt.tsp;
1740 
1741  /* kacq header */
1742  fprintf(fp, "GE_KTACQ\t201\t0\n");
1743  fprintf(fp, "num_sampling_patterns\t%d\n", num_echoes);
1744  fprintf(fp, "num_mask_patterns\t%d\n", 0);
1745  fprintf(fp, "kx_peak_pos\t%d\n", arc_kx_peak_pos);
1746  /* fprintf(fp, "ky_peak_pos\t%d\n", arc_ky_peak_pos); */
1747  fprintf(fp, "---\n");
1748 
1749  /* Reconstruction schedule */
1750  fprintf(fp, "# Reconstruction schedule\n");
1751  fprintf(fp, "# t, Echo, Cal Table, Cal Pass, Accel Table, Accel Pass, Mask Table\n");
1752  fprintf(fp, "RECON_SCHEDULE\t%d\t%d\n", num_echoes, 7);
1753  fprintf(fp, "---\n");
1754  for (echo_index = 0; echo_index < num_echoes; echo_index++) {
1755  fprintf(fp,"%d\t%d\t%d\t%d\t%d\t%d\t%d\n", 0, echo_index, -1, 0, echo_index, 0, -1);
1756  }
1757 
1758  /* Accelerated sampling pattern */
1759 for (echo_index = 0; echo_index < num_echoes; echo_index++) {
1760 
1761  fprintf(fp, "# Sampling Pattern 0 (Accel)\n");
1762  fprintf(fp, "# View Offset, Pass Offset, ky, kz\n");
1763 
1764  fprintf(fp, "SAMPLING_PATTERN\t%d\t%d\n", phaser->numlinestoacq * numzencodes, 4);
1765  fprintf(fp, "max_stride\t%d\t%d\n", phaser->R, (zphaser != NULL) ? zphaser->R : 1);
1766  int dimy;
1767  if (phaser->nover != 0) {
1768  dimy = phaser->res / 2 + abs(phaser->nover); /* half nex */
1769  } else {
1770  dimy = phaser->res;
1771  }
1772  fprintf(fp, "pattern_dimensions\t%d\t%d\n", dimy, (zphaser != NULL) ? exist(opslquant) : 1);
1773  fprintf(fp, "---\n");
1774  for (slice = 0; slice < numzencodes; slice++) {
1775  for (view = 0; view < phaser->numlinestoacq; view++) {
1776  if (zphaser != NULL)
1777  fprintf(fp, "%d\t%d\t%d\t%d\n", phaser->linetoacq[view] + 1 + (zphaser->linetoacq[view] * num_echoes + echo_index) * rhdayres, 0, phaser->linetoacq[view], zphaser->linetoacq[slice]);
1778  else
1779  fprintf(fp, "%d\t%d\t%d\t%d\n", phaser->linetoacq[view] + 1 + echo_index * rhdayres, 0, phaser->linetoacq[view], 0);
1780  }
1781  }
1782 
1783  } /* echo */
1784 
1785  fclose(fp);
1786 
1787 
1788  return SUCCESS;
1789 
1790 } /* GEReq_predownload_setrecon_writekacq() */
int R
Definition: KSFoundation.h:1723
int res
Definition: KSFoundation.h:1721
int numlinestoacq
Definition: KSFoundation.h:1727
int linetoacq[KS_MAX_PHASEDYN]
Definition: KSFoundation.h:1728
int rhkacq_uid
int view
Definition: GERequired.e:3728
int nover
Definition: KSFoundation.h:1722
FILTER_INFO filt
Definition: KSFoundation.h:843
KS_READ acq
Definition: KSFoundation.h:1549
int time2center
Definition: KSFoundation.h:1560
int acqdelay
Definition: KSFoundation.h:1555

◆ ks_get_unique_y_from_pecoords()

int ks_get_unique_y_from_pecoords ( const KS_KSPACE_ACQ kacq)
1811  {
1812  if (kacq->coords == NULL) {
1813  KS_THROW("kacq->coords is NULL");
1814  return 0;
1815  }
1816  qsort(kacq->coords, kacq->num_coords, sizeof(KS_KCOORD), &ks_comp_kcoord_y_z);
1817 
1818  int num_unique = 1;
1819  int prev_y = kacq->coords[0].y;
1820  int i;
1821 
1822  /* Count unique coordinates */
1823  for (i = 1; i < kacq->num_coords; i++) {
1824  if (kacq->coords[i].y != prev_y) {
1825  num_unique++;
1826  prev_y = kacq->coords[i].y;
1827  }
1828  }
1829 
1830  return num_unique;
1831 
1832 } /* ks_get_unique_y_from_pecoords() */
KS_KCOORD * coords
Definition: KSFoundation.h:2228
int ks_comp_kcoord_y_z(const void *a, const void *b)
ADDTITLEHERE
Definition: KSFoundation_host.c:8314
ADDTITLEHERE
Definition: KSFoundation.h:2200
int num_coords
Definition: KSFoundation.h:2229
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
KS_KSPACE_ACQ kacq
Definition: ksepi_implementation.e:355
int y
Definition: KSFoundation.h:2201

◆ ks_get_unique_z_from_pecoords()

int ks_get_unique_z_from_pecoords ( const KS_KSPACE_ACQ kacq)
1837  {
1838  if (kacq->coords == NULL) {
1839  KS_THROW("kacq->coords is NULL");
1840  return 0;
1841  }
1842  qsort(kacq->coords, kacq->num_coords, sizeof(KS_KCOORD), &ks_comp_kcoord_z_y);
1843 
1844  int num_unique = 1;
1845  int prev_y = kacq->coords[0].z;
1846  int i;
1847 
1848  for (i = 1; i < kacq->num_coords; i++) {
1849  if (kacq->coords[i].z != prev_y) {
1850  num_unique++;
1851  prev_y = kacq->coords[i].z;
1852  }
1853  }
1854 
1855  return num_unique;
1856 
1857 } /* ks_get_unique_z_from_pecoords() */
KS_KCOORD * coords
Definition: KSFoundation.h:2228
int z
Definition: KSFoundation.h:2202
ADDTITLEHERE
Definition: KSFoundation.h:2200
int num_coords
Definition: KSFoundation.h:2229
int ks_comp_kcoord_z_y(const void *a, const void *b)
ADDTITLEHERE
Definition: KSFoundation_host.c:8293
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
KS_KSPACE_ACQ kacq
Definition: ksepi_implementation.e:355

◆ ks_get_ynover_from_pecoords()

int ks_get_ynover_from_pecoords ( const KS_KSPACE_ACQ kacq)
1862  {
1863  if (kacq->coords == NULL) {
1864  KS_THROW("kacq->coords is NULL");
1865  return 0;
1866  }
1867  qsort(kacq->coords, kacq->num_coords, sizeof(KS_KCOORD), &ks_comp_kcoord_y_z);
1868 
1869  /* Shift coordinates */
1870  int nover_y_pre = kacq->coords[0].y;
1871  int nover_y_post = kacq->coords[kacq->num_coords-1].y + 1;
1872 
1873 
1874  return IMin(2, abs(nover_y_pre), abs(nover_y_post));
1875 
1876 } /* ks_get_ynover_from_pecoords() */
KS_KCOORD * coords
Definition: KSFoundation.h:2228
int ks_comp_kcoord_y_z(const void *a, const void *b)
ADDTITLEHERE
Definition: KSFoundation_host.c:8314
ADDTITLEHERE
Definition: KSFoundation.h:2200
int num_coords
Definition: KSFoundation.h:2229
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
KS_KSPACE_ACQ kacq
Definition: ksepi_implementation.e:355
int y
Definition: KSFoundation.h:2201

◆ ks_get_znover_from_pecoords()

int ks_get_znover_from_pecoords ( const KS_KSPACE_ACQ kacq)
1881  {
1882  if (kacq->coords == NULL) {
1883  KS_THROW("kacq->coords is NULL");
1884  return 0;
1885  }
1886  qsort(kacq->coords, kacq->num_coords, sizeof(KS_KCOORD), &ks_comp_kcoord_z_y);
1887 
1888  /* Shift coordinates */
1889  int nover_z_pre = kacq->coords[0].z;
1890  int nover_z_post = kacq->coords[kacq->num_coords-1].z + 1;
1891 
1892 
1893  return IMin(2, abs(nover_z_pre), abs(nover_z_post));
1894 
1895 } /* ks_get_znover_from_pecoords() */
KS_KCOORD * coords
Definition: KSFoundation.h:2228
int z
Definition: KSFoundation.h:2202
ADDTITLEHERE
Definition: KSFoundation.h:2200
int num_coords
Definition: KSFoundation.h:2229
int ks_comp_kcoord_z_y(const void *a, const void *b)
ADDTITLEHERE
Definition: KSFoundation_host.c:8293
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
KS_KSPACE_ACQ kacq
Definition: ksepi_implementation.e:355

◆ ks_get_ry_from_pecoords()

int ks_get_ry_from_pecoords ( const KS_KSPACE_ACQ kacq)
1900  {
1901  if (kacq->coords == NULL) {
1902  KS_THROW("kacq->coords is NULL");
1903  return 0;
1904  }
1905  int r = 1;
1906  int i;
1907  qsort(kacq->coords, kacq->num_coords, sizeof(KS_KCOORD), &ks_comp_kcoord_z_y);
1908  for (i = 0; i < (kacq->num_coords-1); i++) {
1909  KS_KCOORD* cur_coord = kacq->coords + i;
1910  KS_KCOORD* next_coord = cur_coord + 1;
1911  if (cur_coord->z == next_coord->z) {
1912  r = IMax(2, r, next_coord->y - cur_coord->y);
1913  }
1914  }
1915  return r;
1916 
1917 } /* ks_get_ry_from_pecoords() */
KS_KCOORD * coords
Definition: KSFoundation.h:2228
int z
Definition: KSFoundation.h:2202
ADDTITLEHERE
Definition: KSFoundation.h:2200
int num_coords
Definition: KSFoundation.h:2229
int ks_comp_kcoord_z_y(const void *a, const void *b)
ADDTITLEHERE
Definition: KSFoundation_host.c:8293
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
KS_KSPACE_ACQ kacq
Definition: ksepi_implementation.e:355
int y
Definition: KSFoundation.h:2201

◆ ks_get_rz_from_pecoords()

int ks_get_rz_from_pecoords ( const KS_KSPACE_ACQ kacq)
1922  {
1923  int r = 1;
1924  int i;
1925 
1926  if (kacq->coords == NULL) {
1927  KS_THROW("kacq->coords is NULL");
1928  return 0;
1929  }
1930 
1931  qsort(kacq->coords, kacq->num_coords, sizeof(KS_KCOORD), &ks_comp_kcoord_y_z);
1932  for (i = 0; i < (kacq->num_coords-1); i++) {
1933  KS_KCOORD* cur_coord = kacq->coords + i;
1934  KS_KCOORD* next_coord = cur_coord + 1;
1935  if (cur_coord->y == next_coord->y) {
1936  r = IMax(2, r, next_coord->z - cur_coord->z);
1937  }
1938  }
1939  return r;
1940 
1941 } /* ks_get_rz_from_pecoords() */
KS_KCOORD * coords
Definition: KSFoundation.h:2228
int z
Definition: KSFoundation.h:2202
int ks_comp_kcoord_y_z(const void *a, const void *b)
ADDTITLEHERE
Definition: KSFoundation_host.c:8314
ADDTITLEHERE
Definition: KSFoundation.h:2200
int num_coords
Definition: KSFoundation.h:2229
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
KS_KSPACE_ACQ kacq
Definition: ksepi_implementation.e:355
int y
Definition: KSFoundation.h:2201

◆ ks_get_cal_z_from_pecoords()

int ks_get_cal_z_from_pecoords ( const KS_KSPACE_ACQ kacq)
1946  {
1947  if (kacq->coords == NULL) {
1948  KS_THROW("kacq->coords is NULL");
1949  return 0;
1950  }
1951  int max_contiguous = 1;
1952  int cur_contiguous = 1;
1953  int i;
1954  qsort(kacq->coords, kacq->num_coords, sizeof(KS_KCOORD), &ks_comp_kcoord_y_z);
1955  for (i = 1; i < kacq->num_coords; i++) {
1956  KS_KCOORD* cur_coord = kacq->coords + i;
1957  KS_KCOORD* prev_coord = cur_coord - 1;
1958  if ( (cur_coord->y == prev_coord->y) &&
1959  (cur_coord->z == prev_coord->z + 1) ) {
1960  cur_contiguous++;
1961  } else {
1962  max_contiguous = IMax(2, max_contiguous, cur_contiguous);
1963  cur_contiguous = 1;
1964  }
1965 
1966  }
1967  return max_contiguous;
1968 
1969 } /* ks_get_cal_z_from_pecoords() */
KS_KCOORD * coords
Definition: KSFoundation.h:2228
int z
Definition: KSFoundation.h:2202
int ks_comp_kcoord_y_z(const void *a, const void *b)
ADDTITLEHERE
Definition: KSFoundation_host.c:8314
ADDTITLEHERE
Definition: KSFoundation.h:2200
int num_coords
Definition: KSFoundation.h:2229
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
KS_KSPACE_ACQ kacq
Definition: ksepi_implementation.e:355
int y
Definition: KSFoundation.h:2201

◆ ks_get_cal_y_from_pecoords()

int ks_get_cal_y_from_pecoords ( const KS_KSPACE_ACQ kacq)
1974  {
1975  if (kacq->coords == NULL) {
1976  KS_THROW("kacq->coords is NULL");
1977  return 0;
1978  }
1979  int max_contiguous = 1;
1980  int cur_contiguous = 1;
1981  int i;
1982  qsort(kacq->coords, kacq->num_coords, sizeof(KS_KCOORD), &ks_comp_kcoord_z_y);
1983  for (i = 1; i < kacq->num_coords; i++) {
1984  KS_KCOORD* cur_coord = kacq->coords + i;
1985  KS_KCOORD* prev_coord = cur_coord - 1;
1986  if ( (cur_coord->z == prev_coord->z) &&
1987  (cur_coord->y == prev_coord->y + 1) ) {
1988  cur_contiguous++;
1989  } else {
1990  max_contiguous = IMax(2, max_contiguous, cur_contiguous);
1991  cur_contiguous = 1;
1992  }
1993 
1994  }
1995  return max_contiguous;
1996 
1997 } /* ks_get_cal_y_from_pecoords() */
KS_KCOORD * coords
Definition: KSFoundation.h:2228
int z
Definition: KSFoundation.h:2202
ADDTITLEHERE
Definition: KSFoundation.h:2200
int num_coords
Definition: KSFoundation.h:2229
int ks_comp_kcoord_z_y(const void *a, const void *b)
ADDTITLEHERE
Definition: KSFoundation_host.c:8293
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
KS_KSPACE_ACQ kacq
Definition: ksepi_implementation.e:355
int y
Definition: KSFoundation.h:2201

◆ GEReq_kacq_get_params()

ks_kacq_coord_params_t GEReq_kacq_get_params ( const KS_KSPACE_ACQ kacq)
2002  {
2004 
2007 
2010 
2011 
2014  out.extent_phase = kacq->matrix_size[YGRAD];
2015  out.extent_slice = IMax(2, kacq->matrix_size[ZGRAD], 1);
2018 
2019  return out;
2020 
2021 } /* GEReq_kacq_get_params() */
int max_stride_phase
Definition: GERequired.e:1796
int extent_phase
Definition: GERequired.e:1800
int nover_phase
Definition: GERequired.e:1802
int max_stride_slice
Definition: GERequired.e:1797
int ks_get_cal_z_from_pecoords(const KS_KSPACE_ACQ *kacq)
Definition: GERequired.e:1946
int matrix_size[3]
Definition: KSFoundation.h:2230
int max_contigous_phase
Definition: GERequired.e:1798
int unique_slice
Definition: GERequired.e:1805
int extent_slice
Definition: GERequired.e:1801
int ks_get_ry_from_pecoords(const KS_KSPACE_ACQ *kacq)
Definition: GERequired.e:1900
int ks_get_cal_y_from_pecoords(const KS_KSPACE_ACQ *kacq)
Definition: GERequired.e:1974
int ks_get_unique_y_from_pecoords(const KS_KSPACE_ACQ *kacq)
Definition: GERequired.e:1811
int nover_slice
Definition: GERequired.e:1803
int ks_get_ynover_from_pecoords(const KS_KSPACE_ACQ *kacq)
Definition: GERequired.e:1862
int ks_get_rz_from_pecoords(const KS_KSPACE_ACQ *kacq)
Definition: GERequired.e:1922
int unique_phase
Definition: GERequired.e:1804
int max_contigous_slice
Definition: GERequired.e:1799
KS_KSPACE_ACQ kacq
Definition: ksepi_implementation.e:355
Definition: GERequired.e:1795
int ks_get_znover_from_pecoords(const KS_KSPACE_ACQ *kacq)
Definition: GERequired.e:1881
int ks_get_unique_z_from_pecoords(const KS_KSPACE_ACQ *kacq)
Definition: GERequired.e:1837

◆ GEReq_writekacq()

STATUS GEReq_writekacq ( const int  nrecon_schedule_entries,
KS_KACQ_RECONSHEDULE_ENTRY recon_schedule,
const int  num_patterns,
const KS_KSPACE_ACQ ks_kacq 
)
2029  {
2030 
2031  const int nmask_patterns = 0;
2032  /* start off getting a file pointer */
2033  const CHAR *kacqFilenameBase = "kacq_yz.txt";
2034  FILE *kacq;
2035  CHAR kacqFilename[1024];
2036  CHAR kacqFilenameFull[1024];
2037 #ifdef PSD_HW
2038  #if EPIC_RELEASE > 29
2039  const CHAR kacqPath[BUFSIZ] = "/srv/nfs/psd/var/psddata/";
2040  #else
2041  const CHAR kacqPath[BUFSIZ] = "/usr/g/psddata/";
2042  #endif
2043  sprintf(kacqFilename, "%s.%d", kacqFilenameBase, rhkacq_uid);
2044 #else
2045  const CHAR *kacqPath = "./";
2046  sprintf(kacqFilename, "%s", kacqFilenameBase);
2047 #endif
2048  sprintf(kacqFilenameFull, "%s%s", kacqPath, kacqFilename);
2049 
2050  kacq = fopen(kacqFilenameFull, "w");
2051 
2052  ks_dbg("Print things to %s", kacqFilename);
2053 
2054  /* next, we write a header */
2055  fprintf(kacq, "GE_KTACQ\t%d\t%d\n", 201 /*KACQ_REV_MAJOR*/, 0/*KACQ_REV_MINOR*/);
2056  fprintf(kacq, "num_sampling_patterns\t%d\n", num_patterns);
2057  fprintf(kacq, "num_mask_patterns\t%d\n", nmask_patterns);
2058 
2059  /* Not required
2060  fprintf(kacq, "kx_peak_pos\t%d\n", kx_peak_pos);
2061  */
2062  fprintf(kacq, "---\n");
2063 
2064  /* print out reconstruction schedule */
2065  fprintf(kacq, "# Reconstruction schedule\n");
2066  fprintf(kacq, "# t, Echo, Cal Table, Cal Pass, Accel Table, Accel Pass, Mask Table\n");
2067  fprintf(kacq, "RECON_SCHEDULE\t%d\t%d\n", nrecon_schedule_entries, 7);
2068  fprintf(kacq, "---\n");
2069 
2070  const int TAB_DEPTH = 256;
2071  if (nrecon_schedule_entries > TAB_DEPTH) {
2072  return KS_THROW("Wow, you'll need to increase the reconschedule table depth to at least %d", nrecon_schedule_entries);
2073  }
2074  int acq_table_mapping[TAB_DEPTH];
2075  int cal_table_mapping[TAB_DEPTH];
2076  int msk_table_mapping[TAB_DEPTH];
2077  int num_acq_patterns = 0;
2078  int num_cal_patterns = 0;
2079  int num_msk_patterns = 0;
2080  int i;
2081  int num_echos = 0;
2082  for (i = 0; i < nrecon_schedule_entries; i++) {
2083 
2084  KS_KACQ_RECONSHEDULE_ENTRY entry = recon_schedule[i];
2085  int acq_table_pos;
2086  if (entry.sampling_pattern_offset == KS_NOTSET) {
2087  return KS_THROW("All reconshedule entries require a valid sampling pattern.");
2088  } else {
2089  acq_table_pos = num_acq_patterns; /* direct mapping entry_index->acq_index */
2090  acq_table_mapping[num_acq_patterns] = entry.sampling_pattern_offset;
2091  num_acq_patterns++;
2092  }
2093  int cal_table_pos;
2094  if (entry.calibration_pattern_offset == KS_NOTSET) {
2095  cal_table_pos = KS_NOTSET;
2096  } else {
2097  cal_table_pos = nrecon_schedule_entries + num_cal_patterns; /* after the acq patterns */
2098  cal_table_mapping[num_cal_patterns] = entry.calibration_pattern_offset;
2099  num_cal_patterns++;
2100  }
2101  int mask_table_pos;
2102  if (entry.mask_pattern_offset == KS_NOTSET) {
2103  mask_table_pos = KS_NOTSET;
2104  } else {
2105  mask_table_pos = num_msk_patterns; /* seperate table */
2106  msk_table_mapping[num_msk_patterns] = entry.mask_pattern_offset;
2107  num_msk_patterns++;
2108  }
2109  fprintf(kacq, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
2110  /*t, Echo, Cal Table, Cal Pass, Accel Table, Accel Pass, Mask Table\*/
2111  i, entry.echo_index, cal_table_pos, i, acq_table_pos, i, mask_table_pos);
2112 
2113  if (num_echos < entry.echo_index) {
2114  num_echos = entry.echo_index;
2115  }
2116 
2117  }
2118  /* does this match what we said? */
2119  if (num_echos != (rhnecho-1)) {
2120  return KS_THROW("There appears to be a mismatch between the recon schedule and the nechoes in the psd (%d != %d)", num_echos, rhnecho-1);
2121  } else {
2122  num_echos++; /* +1 for the number of echos not the index */
2123  }
2124 
2125  /* write out the acq "sampling patterns" one for each recon entry */
2126  int pattern;
2127  for (i = 0; i < num_acq_patterns; i++) {
2128  pattern = acq_table_mapping[i];
2129  /* intialise some variables */
2130  ks_kacq_coord_params_t params = GEReq_kacq_get_params(ks_kacq + pattern);
2131 
2132  /* time to write to the file */
2133  fprintf(kacq, "# Sampling Pattern %d (Accel)\n", i);
2134  fprintf(kacq, "# View Offset, Pass Offset, ky, kz\n");
2135  fprintf(kacq, "SAMPLING_PATTERN\t%d\t%d\n", ks_kacq[pattern].num_coords, 4);
2136  fprintf(kacq, "max_stride\t%d\t%d\n", params.max_stride_phase, params.max_stride_slice);
2137  const int dim_y = rhhnover == 0 ? params.extent_phase
2138  : params.extent_phase/2 + params.nover_phase + params.max_stride_phase -1 /* Expect R-1 blank lines */;
2139  fprintf(kacq, "pattern_dimensions\t%d\t%d\n", dim_y, params.extent_slice);
2140  fprintf(kacq, "---\n");
2141  int coord;
2142  for (coord = 0; coord < ks_kacq[pattern].num_coords; coord++) {
2143  KS_KCOORD kcoord = ks_kacq[pattern].coords[coord];
2144  kcoord.y += params.extent_phase / 2;
2145  kcoord.z += params.extent_slice / 2;
2146  int frame = kcoord.y + 1 + (params.extent_phase + 1) * (num_echos * kcoord.z + recon_schedule[i].echo_index);
2147  if ((kcoord.y != KS_NOTSET) && (kcoord.z != KS_NOTSET)) {
2148  fprintf(kacq, "%d\t%d\t%d\t%d\n", frame, 0, kcoord.y, kcoord.z);
2149  }
2150  }
2151  }
2152 
2153  /* write out the cal "sampling patterns" offset by nrecon_schedule_entries */
2154  for (i = 0; i < num_cal_patterns; i++) {
2155  pattern = cal_table_mapping[i];
2156  /* intialise some variables */
2157  ks_kacq_coord_params_t params = GEReq_kacq_get_params(ks_kacq + pattern);
2158 
2159  /* time to write to the file */
2160  fprintf(kacq, "# Sampling Pattern %d (Calibration)\n", i + nrecon_schedule_entries);
2161  fprintf(kacq, "# View Offset, Pass Offset, ky, kz\n");
2162  fprintf(kacq, "SAMPLING_PATTERN\t%d\t%d\n", ks_kacq[pattern].num_coords, 4);
2163  fprintf(kacq, "pattern_dimensions\t%d\t%d\n",
2164  params.extent_phase, params.extent_slice);
2165  fprintf(kacq, "cal_apodization_kasier_bessel_beta\t%f\t%f\n", 1.0, 1.0);
2166  /* Some extra options ---
2167  fprintf(kacq, "fully_sampled_start\t%d\t%d\n",
2168  calRegion.phaseCutoffLower, calRegion.sliceCutoffLower);
2169  fprintf(kacq, "fully_sampled_length\t%d\t%d\n",
2170  calRegion.phaseCutoffUpper - calRegion.phaseCutoffLower + 1,
2171  calRegion.sliceCutoffUpper - calRegion.sliceCutoffLower + 1);*/
2172  fprintf(kacq, "---\n");
2173  int coord;
2174  for (coord = 0; coord < ks_kacq[pattern].num_coords; coord++) {
2175  KS_KCOORD kcoord = ks_kacq[pattern].coords[coord];
2176  kcoord.y += params.extent_phase / 2;
2177  kcoord.z += params.extent_slice / 2;
2178  int frame = kcoord.y + 1 + (params.extent_phase + 1) * (num_echos * kcoord.z + recon_schedule[pattern].echo_index);
2179  if ((kcoord.y != KS_NOTSET) && (kcoord.z != KS_NOTSET)) {
2180  fprintf(kacq, "%d\t%d\t%d\t%d\n", frame, 0, kcoord.y, kcoord.z);
2181  }
2182  }
2183  }
2184 
2185  /* write out the mask patterns at the end */
2186  for (i = 0; i < num_msk_patterns; i++) {
2187  pattern = msk_table_mapping[i];
2188  ks_kacq_coord_params_t params = GEReq_kacq_get_params(ks_kacq + pattern);
2189 
2190  fprintf(kacq, "# Mask pattern %d\n", i);
2191  fprintf(kacq, "# ky, kz\n");
2192  fprintf(kacq, "MASK_PATTERN\t%d\t%d\n", ks_kacq[pattern].num_coords, 2);
2193  fprintf(kacq, "pattern_dimensions\t%d\t%d\n",
2194  params.extent_phase, params.extent_slice);
2195  fprintf(kacq, "---\n");
2196  int coord;
2197  for (coord = 0; coord < ks_kacq[pattern].num_coords; coord++) {
2198  KS_KCOORD kcoord = ks_kacq[pattern].coords[coord];
2199  kcoord.y += params.extent_phase / 2;
2200  kcoord.z += params.extent_slice / 2;
2201  fprintf(kacq, "%d\t%d\n", kcoord.y, kcoord.z);
2202  }
2203  }
2204 
2205  /* close the file */
2206  fclose(kacq);
2207 
2208 
2209  return SUCCESS;
2210 
2211 } /* GEReq_writekacq() */
int calibration_pattern_offset
Definition: KSFoundation.h:2298
int max_stride_phase
Definition: GERequired.e:1796
int extent_phase
Definition: GERequired.e:1800
#define KS_NOTSET
Definition: KSFoundation.h:115
int nover_phase
Definition: GERequired.e:1802
KS_KCOORD * coords
Definition: KSFoundation.h:2228
int max_stride_slice
Definition: GERequired.e:1797
ks_kacq_coord_params_t GEReq_kacq_get_params(const KS_KSPACE_ACQ *kacq)
Definition: GERequired.e:2002
int echo_index
Definition: KSFoundation.h:2296
int extent_slice
Definition: GERequired.e:1801
An entry into the table that is written into the k_acq file when using GE&#39;s arc reconstruction
Definition: KSFoundation.h:2295
int rhkacq_uid
int z
Definition: KSFoundation.h:2202
STATUS STATUS ks_dbg(const char *format,...) __attribute__((format(printf
Common debug message function for HOST and TGT
ADDTITLEHERE
Definition: KSFoundation.h:2200
int num_coords
Definition: KSFoundation.h:2229
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
int mask_pattern_offset
Definition: KSFoundation.h:2299
KS_KSPACE_ACQ kacq
Definition: ksepi_implementation.e:355
Definition: GERequired.e:1795
int sampling_pattern_offset
Definition: KSFoundation.h:2297
int y
Definition: KSFoundation.h:2201

◆ GEReq_writekacq_from_coords()

STATUS GEReq_writekacq_from_coords ( const KS_KSPACE_ACQ kacq,
const int  nechoes 
)
2216  {
2217  KS_KACQ_RECONSHEDULE_ENTRY recon_table[16];
2218  int echo;
2219  for (echo = 0; echo < nechoes; echo++) {
2220  recon_table[echo].sampling_pattern_offset = 0;
2221  recon_table[echo].calibration_pattern_offset = KS_NOTSET;
2222  recon_table[echo].mask_pattern_offset = KS_NOTSET;
2223  recon_table[echo].echo_index = echo;
2224  }
2225  return GEReq_writekacq(nechoes, recon_table, nechoes, kacq);
2226 
2227 } /* GEReq_writekacq_from_coords() */
int calibration_pattern_offset
Definition: KSFoundation.h:2298
#define KS_NOTSET
Definition: KSFoundation.h:115
int echo_index
Definition: KSFoundation.h:2296
An entry into the table that is written into the k_acq file when using GE&#39;s arc reconstruction
Definition: KSFoundation.h:2295
STATUS GEReq_writekacq(const int nrecon_schedule_entries, KS_KACQ_RECONSHEDULE_ENTRY *recon_schedule, const int num_patterns, const KS_KSPACE_ACQ *ks_kacq)
Definition: GERequired.e:2026
int mask_pattern_offset
Definition: KSFoundation.h:2299
KS_KSPACE_ACQ kacq
Definition: ksepi_implementation.e:355
int sampling_pattern_offset
Definition: KSFoundation.h:2297

◆ GEReq_predownload_setrecon_accel_from_coords()

STATUS GEReq_predownload_setrecon_accel_from_coords ( const KS_KSPACE_ACQ kacq,
const int  is_pf_y,
const int  nechoes 
)

Sets rh*** variables related to parallel imaging using kSpace coordinates

Parameters
[in]kacqk-Space coordinates.
[in]is_pf_yFlag if partial Fourier along Y.
[in]nechoesNumber of echoes. Only relevant for kacq file, i.e. ARC + online recon
Return values
STATUSSUCCESS or FAILURE
2240  {
2241 
2243 
2244  if ((params.max_stride_phase < 1) || (params.max_stride_slice < 1)) {
2245  return KS_THROW("Max stride cannot be negative (Ry == %d, Rz == %d)", params.max_stride_phase, params.max_stride_slice);
2246  }
2247 
2248  /* make sure we will be able to set all these CVs */
2249  _rhasset.fixedflag = FALSE;
2250  _rhasset_R.fixedflag = FALSE;
2251  _rhhnover.fixedflag = FALSE;
2252  _rhnframes.fixedflag = FALSE;
2253  _rhdayres.fixedflag = FALSE;
2254 
2255  rhtype1 |= RHTYP1BAM0FILL; /* zero fill bam before start of acq */
2256 
2257  int nover_y = 0;
2258  int nframes = params.extent_phase;
2259  if (is_pf_y) {
2260  nover_y = RUP_FACTOR(params.nover_phase, 2); /* Note that rhhnover must be even but it's fine to scan with odd */
2261  nframes /= 2;
2262  rhtype |= RHTYPFRACTNEX;
2263  } else {
2264  rhtype &= ~RHTYPFRACTNEX;
2265  }
2266 
2267 
2268  rhasset_R = 1.0 / params.max_stride_phase;
2269  rhassetsl_R = 1.0 / params.max_stride_slice;
2270 
2271  if (params.max_stride_phase > 1) {
2272  if (params.max_contigous_phase > 1) {
2273  rhasset = ACCEL_ARC;
2274  } else {
2275  rhasset = ASSET_SCAN; /* There are no ACS lines */
2276  }
2277  } else {
2278  rhasset = 0;
2279  }
2280  if (rhasset == ASSET_SCAN) {
2281  /* ASSET uses compressed BAM, i.e. stores only the acquired lines */
2282  rhhnover = nover_y / params.max_stride_phase;
2283  rhnframes = nframes / params.max_stride_phase;
2284  rhdayres = rhnframes + rhhnover + 1;
2285  } else {
2286  rhhnover = nover_y;
2287  if (rhasset == ACCEL_ARC) {
2288  rhnframes = params.unique_phase; /* Previously numlinestoacq */
2289  if (nover_y == 0) {
2290  rhdayres = params.extent_phase + 1;
2291  } else {
2292  rhdayres = rhhnover + params.extent_phase/2 + 1;
2293  }
2294  } else {
2295  rhnframes = nframes;
2296  rhdayres = rhhnover + rhnframes + 1; /* As given by Abel */
2297  }
2298  }
2299 
2300  return GEReq_writekacq_from_coords(kacq, nechoes);
2301 
2302 } /* GEReq_predownload_setrecon_accel_from_coords() */
int max_stride_phase
Definition: GERequired.e:1796
int extent_phase
Definition: GERequired.e:1800
int nover_phase
Definition: GERequired.e:1802
int max_stride_slice
Definition: GERequired.e:1797
ks_kacq_coord_params_t GEReq_kacq_get_params(const KS_KSPACE_ACQ *kacq)
Definition: GERequired.e:2002
int max_contigous_phase
Definition: GERequired.e:1798
STATUS GEReq_writekacq_from_coords(const KS_KSPACE_ACQ *kacq, const int nechoes)
Definition: GERequired.e:2216
int unique_phase
Definition: GERequired.e:1804
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
KS_KSPACE_ACQ kacq
Definition: ksepi_implementation.e:355
Definition: GERequired.e:1795

◆ GEReq_predownload_setrecon_accel()

STATUS GEReq_predownload_setrecon_accel ( const KS_READTRAP *const  readtrap,
const KS_PHASER *const  phaser,
const KS_PHASER *const  zphaser,
int  datadestination 
)

Sets rh*** variables related to parallel imaging acceleration

Parameters
[in]readtrapPointer to KS_READTRAP
[in]phaserPointer to KS_PHASER (phase)
[in]zphaserPointer to KS_PHASER (slice). NULL for 2D
[in]datadestinationValue to assign to rhexecctrl (c.f. epic.h)
Return values
STATUSSUCCESS or FAILURE
2318  {
2319  STATUS status;
2320 
2321  /* make sure we will be able to set all these CVs */
2322  _rhasset.fixedflag = FALSE;
2323  _rhasset_R.fixedflag = FALSE;
2324  _rhhnover.fixedflag = FALSE;
2325  _rhnframes.fixedflag = FALSE;
2326  _rhdayres.fixedflag = FALSE;
2327 
2328  if (phaser->R <= 1 && (zphaser == NULL || zphaser->R <= 1)) {
2329  rhasset = 0;
2330  rhasset_R = 1.0;
2331  rhassetsl_R = 1.0;
2332  return SUCCESS;
2333  }
2334 
2335  rhtype1 |= RHTYP1BAM0FILL; /* once more, just in case */
2336 
2337  if (datadestination & RHXC_XFER_IM) {
2338  /* if we are going to use GE recon (RHXC_XFER_IM = 8) */
2339 
2340  if (phaser->nacslines > 0) { /* ARC */
2341 
2342  /* ARC uses full BAM, i.e. stores the acquired lines at their proper locations in k-space with zero lines in between */
2343  rhhnover = abs(phaser->nover);
2344  rhnframes = phaser->numlinestoacq; /* # of acquired lines */
2345  rhdayres = (phaser->nover != 0) ? (phaser->res/2 + abs(phaser->nover) + 1) : (phaser->res + 1);
2346 
2347  rhasset = ACCEL_ARC; /* tell recon we are doing ARC only if we have ACS lines */
2348  status = GEReq_predownload_setrecon_writekacq(readtrap, phaser, zphaser);
2349  KS_RAISE(status);
2350 
2351  } else { /* ASSET */
2352 
2353  /* ASSET uses compressed BAM, i.e. stores only the acquired lines */
2354  rhhnover = abs(phaser->nover) / phaser->R;
2355  rhnframes = (phaser->nover != 0) ? (phaser->res / (2 * phaser->R)) : (phaser->res / phaser->R);
2356  rhdayres = rhnframes + rhhnover + 1;
2357 
2358  rhasset = ASSET_SCAN; /* if we don't have ACS lines, we will need to recon the data using some external calibration */
2359  }
2360 
2361  } else {
2362 
2363  /* store data as ARC (full BAM) */
2364  rhhnover = abs(phaser->nover);
2365  rhnframes = phaser->numlinestoacq; /* # of acquired lines */
2366  rhdayres = (phaser->nover != 0) ? (phaser->res / 2 + abs(phaser->nover) + 1) : (phaser->res + 1);
2367 
2368  rhasset = 0; /* we are going to do the reconstruction offline */
2369  }
2370 
2371  rhasset_R = 1.0 / phaser->R; /* inverse of acceleration factor */
2372  rhassetsl_R = (zphaser != NULL) ? (1.0 / zphaser->R) : 1;
2373 
2374  return SUCCESS;
2375 
2376 } /* GEReq_predownload_setrecon_accel() */
int R
Definition: KSFoundation.h:1723
int res
Definition: KSFoundation.h:1721
int nacslines
Definition: KSFoundation.h:1724
int numlinestoacq
Definition: KSFoundation.h:1727
STATUS GEReq_predownload_setrecon_writekacq(const KS_READTRAP *const readtrap, const KS_PHASER *const phaser, const KS_PHASER *const zphaser)
Writes a kacq_yz.txt.***** file for use with GE&#39;s product ARC recon
Definition: GERequired.e:1710
#define KS_RAISE(status)
Definition: KSFoundation.h:190
int nover
Definition: KSFoundation.h:1722

◆ GEReq_predownload_setrecon_phase()

void GEReq_predownload_setrecon_phase ( const KS_PHASER *const  phaser,
const float  readfov,
const int  datadestination 
)
2381  {
2382  /* make sure we will be able to set all these CVs */
2383  _rhasset.fixedflag = FALSE;
2384  _rhasset_R.fixedflag = FALSE;
2385  _rhhnover.fixedflag = FALSE;
2386  _rhnframes.fixedflag = FALSE;
2387  _rhdayres.fixedflag = FALSE;
2388 
2389  if (phaser->nover != 0) { /* partial Fourier ky */
2390  rhnframes = phaser->res / 2;
2391  rhtype |= RHTYPFRACTNEX;
2392  } else {
2393  rhnframes = phaser->res;
2394  rhtype &= ~RHTYPFRACTNEX;
2395  }
2396 
2397  rhhnover = abs(phaser->nover);
2398  rhdayres = rhnframes + rhhnover + 1;
2399 
2400 
2401  rhexecctrl = datadestination;
2402  if (op3dgradwarp && !(rhexecctrl & RHXC_XFER_IM)) {
2403  /* 3D gradwarp requires at least one of the following bits set:
2404  #define RHXC_XFER_IM 0x0008 8 (GE online recon)
2405  #define RHXC_SAVE_IM 0x0010 16
2406  */
2407  (rhexecctrl) |= RHXC_SAVE_IM; /* parentheses around rhexecctrl prevents EPIC preprocessor to add fixedflag check */
2408  }
2409 
2410  rhphasescale = phaser->fov / readfov;
2411  if (phaser->R <= 1) {
2412  rhasset = 0;
2413  rhasset_R = 1.0;
2414  return;
2415  }
2416 
2417  rhtype1 |= RHTYP1BAM0FILL; /* once more, just in case */
2418 
2419  if (datadestination & RHXC_XFER_IM) {
2420  /* if we are going to use GE recon (RHXC_XFER_IM = 8) */
2421  if (phaser->nacslines > 0) { /* ARC */
2422  /* ARC uses full BAM, i.e. stores the acquired lines at their proper locations in k-space with zero lines in between */
2423  rhhnover = abs(phaser->nover);
2424  rhnframes = phaser->numlinestoacq; /* # of acquired lines */
2425  rhdayres = (phaser->nover != 0) ? (phaser->res/2 + abs(phaser->nover) + 1) : (phaser->res + 1);
2426  rhasset = ACCEL_ARC; /* tell recon we are doing ARC only if we have ACS lines */
2427  } else { /* ASSET */
2428  /* ASSET uses compressed BAM, i.e. stores only the acquired lines */
2429  rhhnover = abs(phaser->nover) / phaser->R;
2430  rhnframes = (phaser->nover != 0) ? (phaser->res / (2 * phaser->R)) : (phaser->res / phaser->R);
2431  rhdayres = rhnframes + rhhnover + 1;
2432  rhasset = ASSET_SCAN; /* if we don't have ACS lines, we will need to recon the data using some external calibration */
2433  }
2434  } else {
2435  /* store data as ARC (full BAM) */
2436  rhhnover = abs(phaser->nover);
2437  rhnframes = phaser->numlinestoacq; /* # of acquired lines */
2438  rhdayres = (phaser->nover != 0) ? (phaser->res / 2 + abs(phaser->nover) + 1) : (phaser->res + 1);
2439  rhasset = 0; /* we are going to do the reconstruction offline */
2440  }
2441 
2442  rhasset_R = 1.0 / phaser->R; /* inverse of acceleration factor */
2443 
2444 } /* GEReq_predownload_setrecon_phase() */
int R
Definition: KSFoundation.h:1723
int res
Definition: KSFoundation.h:1721
int nacslines
Definition: KSFoundation.h:1724
int numlinestoacq
Definition: KSFoundation.h:1727
int nover
Definition: KSFoundation.h:1722
float fov
Definition: KSFoundation.h:1720

◆ GEReq_predownload_setrecon_readwave()

void GEReq_predownload_setrecon_readwave ( const KS_READWAVE *const  readwave,
const int  yres,
const int  xres,
int  imsize_policy,
int  datadestination 
)
2449  {
2450  int max_xy;
2451 
2452  /* make sure we will be able to set all these CVs */
2453  _rhfrsize.fixedflag = FALSE;
2454  _rhdaxres.fixedflag = FALSE;
2455  _rhvrgf.fixedflag = FALSE;
2456  _rhvrgfxres.fixedflag = FALSE;
2457 
2458  /* raw data freq (x) size (works for both non-VRGF and VRGF) */
2459  rhfrsize = readwave->acq.filt.outputs;
2460  rhdaxres = xres;
2461 
2462 
2463  piforkvrgf = 0; /* 1 causes scan to spawn the vrgf process upon download */
2464  rhtype1 &= ~(RHTYP1FVRGF + RHTYP1PCORVRGF);
2465  rhuser32 = 0.0;
2466  rhuser33 = 0.0;
2467  rhuser34 = 0.0;
2468  rhuser35 = 0.0;
2469 
2470  /* image size */
2471  max_xy = IMax(2, xres, yres);
2472 
2473  rhmethod = 1; /* enable reduced image size, so we are in control */
2474  if (imsize_policy == KS_IMSIZE_MIN256) {
2475  max_xy = IMax(2, max_xy, 256);
2476  } else if (imsize_policy == KS_IMSIZE_POW2) {
2477  max_xy = ks_calc_nextpow2((unsigned int) max_xy); /* round up to nearest power of 2 if imsize_policy = KS_IMSIZE_POW2 */
2478  }
2479 
2480  /* recon image size with optional zerofilling */
2481  if (opzip512 && max_xy < 512) {
2482  max_xy = 512;
2483  } else if (opzip1024 && max_xy < 1024) {
2484  max_xy = 1024;
2485  }
2486  rhimsize = max_xy;
2487  rhrcxres = rhimsize;
2488  rhrcyres = rhimsize;
2489 
2490  /* freq. partial Fourier */
2491  if (abs(readwave->nover) > 0) {
2492  /* fractional echo (partial Fourier kx) */
2493  pitfeextra = rhfrsize * abs(readwave->nover) / (float)(readwave->res/2 + abs(readwave->nover));
2494  } else {
2495  pitfeextra = 0;
2496  }
2497  /* rhheover = pitfeextra; */
2498  rhfeextra = abs(readwave->nover);
2499 
2500  /* chopping control */
2501  rhtype |= RHTYPCHP; /* ( |= 1) no chopping processing needed in recon */
2502 
2503  /* 3D recon flag */
2504  if(opimode == PSD_3D || opimode == PSD_3DM)
2505  rhtype |= RHTYP3D;
2506  else
2507  rhtype &= ~RHTYP3D;
2508 
2509 
2510 } /* GEReq_predownload_setrecon_readwave() */
Definition: KSFoundation.h:2335
Definition: KSFoundation.h:2335
FILTER_INFO filt
Definition: KSFoundation.h:843
unsigned int ks_calc_nextpow2(unsigned int x)
Gives the next higher 2^N for a given number
Definition: KSFoundation_host.c:6128
KS_READ acq
Definition: KSFoundation.h:1606
int res
Definition: KSFoundation.h:1611
int nover
Definition: KSFoundation.h:1612

◆ GEReq_predownload_setrecon_image()

void GEReq_predownload_setrecon_image ( const int  xres,
const int  yres,
const float  xfov,
const float  yfov,
const ks_enum_imsize  imsize_policy 
)
2515  {
2516  /* image size */
2517  int max_xy = IMax(2, xres, yres);
2518 
2519  rhmethod = 1; /* enable reduced image size, so we are in control */
2520  if (imsize_policy == KS_IMSIZE_MIN256) {
2521  max_xy = (max_xy > 256) ? (IMax(2, 512, max_xy))
2522  : 256; /* final image size is either 256, 512, or higher than 512 */
2523  } else if (imsize_policy == KS_IMSIZE_POW2) {
2524  max_xy = ks_calc_nextpow2((unsigned int) max_xy);
2525  }
2526 
2527  /* recon image size with optional zerofilling */
2528  if (opzip512 && max_xy < 512) {
2529  max_xy = 512;
2530  } else if (opzip1024 && max_xy < 1024) {
2531  max_xy = 1024;
2532  }
2533  rhimsize = max_xy;
2534  rhrcxres = rhimsize;
2535  rhrcyres = rhimsize;
2536 
2537  rhphasescale = yfov / xfov;
2538 
2539 } /* GEReq_predownload_setrecon_image() */
Definition: KSFoundation.h:2335
Definition: KSFoundation.h:2335
unsigned int ks_calc_nextpow2(unsigned int x)
Gives the next higher 2^N for a given number
Definition: KSFoundation_host.c:6128

◆ GEReq_predownload_setrecon_readtrap()

void GEReq_predownload_setrecon_readtrap ( const KS_READTRAP *const  readtrap,
int  datadestination 
)
2544  {
2545 
2546  /* make sure we will be able to set all these CVs */
2547  _rhfrsize.fixedflag = FALSE;
2548  _rhdaxres.fixedflag = FALSE;
2549  _rhvrgf.fixedflag = FALSE;
2550  _rhvrgfxres.fixedflag = FALSE;
2551 
2552  /* raw data freq (x) size (works for both non-VRGF and VRGF) */
2553  rhfrsize = readtrap->acq.filt.outputs;
2554  rhdaxres = readtrap->acq.filt.outputs;
2555 
2556  /* ramp sampling */
2557  rhvrgf = readtrap->rampsampling;
2558  rhvrgfxres = readtrap->res;
2559 
2560  if (readtrap->rampsampling) {
2561  piforkvrgf = 1; /* 1 causes scan to spawn the vrgf process upon download */
2562  rhtype1 |= (RHTYP1FVRGF + RHTYP1PCORVRGF); /* VRGF and VRGFafterPC */
2563 
2564  /* write vrgf.param */
2565  GEReq_predownload_genVRGF(readtrap);
2566 
2567  /* VRGF (rampsampling): Store shape of the read lobe to determine the k-space travel along kx (freq. dir.) for offline VRGF correction */
2568  rhuser32 = readtrap->acq.filt.tsp; /* time between sample points [often 2us] */
2569  rhuser33 = readtrap->grad.amp; /* Readout gradient amplitude */
2570  rhuser34 = (float) (readtrap->grad.plateautime / 2) / 1.0e6; /* half plateau time */
2571  rhuser35 = (float) (readtrap->grad.ramptime) / 1.0e6; /* attack/decay time */
2572  } else {
2573  piforkvrgf = 0;
2574  rhtype1 &= ~(RHTYP1FVRGF + RHTYP1PCORVRGF);
2575  }
2576 
2577  /* freq. partial Fourier */
2578  if (abs(readtrap->nover) > 0) {
2579  /* fractional echo (partial Fourier kx) */
2580  pitfeextra = rhfrsize - readtrap->res / 2;
2581  } else {
2582  pitfeextra = 0;
2583  }
2584  rhfeextra = pitfeextra;
2585 
2586  /* chopping control */
2587  rhtype |= RHTYPCHP; /* ( |= 1) no chopping processing needed in recon */
2588 
2589  /* 3D recon flag */
2590  if (KS_3D_SELECTED)
2591  rhtype |= RHTYP3D;
2592  else
2593  rhtype &= ~RHTYP3D;
2594 
2595  rhexecctrl = datadestination;
2596  if (op3dgradwarp && !(rhexecctrl & RHXC_XFER_IM)) {
2597  /* 3D gradwarp requires at least one of the following bits set:
2598  #define RHXC_XFER_IM 0x0008 8 (GE online recon)
2599  #define RHXC_SAVE_IM 0x0010 16
2600  */
2601  (rhexecctrl) |= RHXC_SAVE_IM; /* parentheses around rhexecctrl prevents EPIC preprocessor to add fixedflag check */
2602  }
2603 
2604  if (datadestination & RHXC_XFER_IM) {
2605  rhdacqctrl &= ~8192; /* enable GE's Orchestra Live recon */
2606  } else {
2607  rhdacqctrl |= 8192; /* disable GE's Orchestra Live recon */
2608  }
2609 
2610 
2611 } /* GEReq_predownload_setrecon_readtrap() */
int plateautime
Definition: KSFoundation.h:672
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
KS_TRAP grad
Definition: KSFoundation.h:1561
STATUS GEReq_predownload_genVRGF(const KS_READTRAP *const readtrap)
Generates the vrgf.param file for rampsampling correction
Definition: GERequired.e:1523
int res
Definition: KSFoundation.h:1552
float amp
Definition: KSFoundation.h:669
FILTER_INFO filt
Definition: KSFoundation.h:843
int nover
Definition: KSFoundation.h:1554
int rampsampling
Definition: KSFoundation.h:1553
KS_READ acq
Definition: KSFoundation.h:1549
int ramptime
Definition: KSFoundation.h:671

◆ GEReq_predownload_setrecon_readphase()

void GEReq_predownload_setrecon_readphase ( const KS_READTRAP *const  readtrap,
const KS_PHASER *const  phaser,
const KS_PHASER *const  zphaser,
int  imsize_policy,
int  datadestination 
)

Sets required global rh*** variables for Cartsian imaging

For Cartesian pulse sequences, using one KS_READTRAP and one KS_PHASER (each of which may have multiple instances), the required rh*** variables are set based on the content of the sequence objects KS_READTRAP (arg 1) and KS_PHASER (arg 2). The fields in each sequence object, including e.g. partial Fourier and rampsampling, controls the setting of GE's rh*** variables. In addition, the third argument specifies the desired upsampling policy for small matrix sizes.

Parameters
[in]readtrapPointer to KS_READTRAP
[in]phaserPointer to KS_PHASER
[in]zphaserPointer to KS_PHASER (slice). NULL for 2D
[in]imsize_policyChoose between KS_IMSIZE_NATIVE, KS_IMSIZE_POW2, KS_IMSIZE_MIN256
[in]datadestinationValue for the rhexecctrl variable. Bitmasks for: KS_SAVEPFILES (dump Pfiles) and KS_GERECON (product recon)
Returns
void
2633  {
2634  int max_xy;
2635 
2636  /* make sure we will be able to set all these CVs */
2637  _rhfrsize.fixedflag = FALSE;
2638  _rhdaxres.fixedflag = FALSE;
2639  _rhdayres.fixedflag = FALSE;
2640  _rhnframes.fixedflag = FALSE;
2641  _rhhnover.fixedflag = FALSE;
2642  _rhvrgf.fixedflag = FALSE;
2643  _rhvrgfxres.fixedflag = FALSE;
2644  _rhasset.fixedflag = FALSE;
2645  _rhasset_R.fixedflag = FALSE;
2646 
2647  /* raw data freq (x) size (works for both non-VRGF and VRGF) */
2648  rhfrsize = readtrap->acq.filt.outputs;
2649  rhdaxres = readtrap->acq.filt.outputs;
2650 
2651  /* ramp sampling */
2652  rhvrgf = readtrap->rampsampling;
2653  rhvrgfxres = readtrap->res;
2654 
2655  if (readtrap->rampsampling) {
2656  piforkvrgf = 1; /* 1 causes scan to spawn the vrgf process upon download */
2657  rhtype1 |= (RHTYP1FVRGF + RHTYP1PCORVRGF); /* VRGF and VRGFafterPC */
2658 
2659  /* write vrgf.param */
2660  GEReq_predownload_genVRGF(readtrap);
2661 
2662  /* VRGF (rampsampling): Store shape of the read lobe to determine the k-space travel along kx (freq. dir.) for offline VRGF correction */
2663  rhuser32 = readtrap->acq.filt.tsp; /* time between sample points [often 2us] */
2664  rhuser33 = readtrap->grad.amp; /* Readout gradient amplitude */
2665  rhuser34 = (float) (readtrap->grad.plateautime / 2) / 1.0e6; /* half plateau time */
2666  rhuser35 = (float) (readtrap->grad.ramptime) / 1.0e6; /* attack/decay time */
2667  } else {
2668  piforkvrgf = 0; /* 1 causes scan to spawn the vrgf process upon download */
2669  rhtype1 &= ~(RHTYP1FVRGF + RHTYP1PCORVRGF);
2670  rhuser32 = 0.0;
2671  rhuser33 = 0.0;
2672  rhuser34 = 0.0;
2673  rhuser35 = 0.0;
2674  }
2675 
2676 
2677  /* image size */
2678  if (phaser != NULL) {
2679  max_xy = IMax(2, readtrap->res, phaser->res);
2680  } else {
2681  max_xy = readtrap->res;
2682  }
2683 
2684  rhmethod = 1; /* enable reduced image size, so we are in control */
2685  if (imsize_policy == KS_IMSIZE_MIN256) {
2686  max_xy = (max_xy > 256) ? 512 : 256; /* final image size is either 512 or 256 */
2687  } else if (imsize_policy == KS_IMSIZE_POW2) {
2688  max_xy = ks_calc_nextpow2((unsigned int) max_xy); /* round up to nearest power of 2 if imsize_policy = KS_IMSIZE_POW2 */
2689  }
2690 
2691  /* recon image size with optional zerofilling */
2692  if (opzip512 && max_xy < 512) {
2693  max_xy = 512;
2694  } else if (opzip1024 && max_xy < 1024) {
2695  max_xy = 1024;
2696  }
2697  rhimsize = max_xy;
2698  rhrcxres = rhimsize;
2699  rhrcyres = rhimsize;
2700 
2701  /* freq. partial Fourier */
2702  if (abs(readtrap->nover) > 0) {
2703  /* fractional echo (partial Fourier kx) */
2704  pitfeextra = rhfrsize - readtrap->res / 2;
2705  } else {
2706  pitfeextra = 0;
2707  }
2708  rhfeextra = pitfeextra;
2709 
2710  /* chopping control */
2711  rhtype |= RHTYPCHP; /* ( |= 1) no chopping processing needed in recon */
2712 
2713  /* 3D recon flag */
2714  if (KS_3D_SELECTED)
2715  rhtype |= RHTYP3D;
2716  else
2717  rhtype &= ~RHTYP3D;
2718 
2719  /* phase encoding (see also GEReq_predownload_setrecon_accel(), which may override these values) */
2720  if (phaser != NULL) {
2721  if (phaser->nover != 0) { /* partial Fourier ky */
2722  rhnframes = phaser->res / 2;
2723  rhtype |= RHTYPFRACTNEX;
2724  } else {
2725  rhnframes = phaser->res;
2726  rhtype &= ~RHTYPFRACTNEX;
2727  }
2728 
2729  rhhnover = abs(phaser->nover);
2730  rhdayres = rhnframes + rhhnover + 1;
2731 
2732  rhexecctrl = datadestination;
2733  if (op3dgradwarp && !(rhexecctrl & RHXC_XFER_IM)) {
2734  /* 3D gradwarp requires at least one of the following bits set:
2735  #define RHXC_XFER_IM 0x0008 8 (GE online recon)
2736  #define RHXC_SAVE_IM 0x0010 16
2737  */
2738  (rhexecctrl) |= RHXC_SAVE_IM; /* parentheses around rhexecctrl prevents EPIC preprocessor to add fixedflag check */
2739  }
2740 
2741  if (datadestination & RHXC_XFER_IM) {
2742  rhdacqctrl &= ~8192; /* enable GE's Orchestra Live recon */
2743  } else {
2744  rhdacqctrl |= 8192; /* disable GE's Orchestra Live recon */
2745  }
2746 
2747  /* Set up ARC/ASSET flags if R > 1 otherwise shut them off */
2748  GEReq_predownload_setrecon_accel(readtrap, phaser, zphaser, datadestination);
2749 
2750  rhphasescale = phaser->fov / readtrap->fov;
2751 
2752  } /* phaser != NULL */
2753 
2754 } /* GEReq_predownload_setrecon_readphase() */
int plateautime
Definition: KSFoundation.h:672
int res
Definition: KSFoundation.h:1721
Definition: KSFoundation.h:2335
float fov
Definition: KSFoundation.h:1551
Definition: KSFoundation.h:2335
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
KS_TRAP grad
Definition: KSFoundation.h:1561
STATUS GEReq_predownload_genVRGF(const KS_READTRAP *const readtrap)
Generates the vrgf.param file for rampsampling correction
Definition: GERequired.e:1523
int res
Definition: KSFoundation.h:1552
float amp
Definition: KSFoundation.h:669
int nover
Definition: KSFoundation.h:1722
FILTER_INFO filt
Definition: KSFoundation.h:843
unsigned int ks_calc_nextpow2(unsigned int x)
Gives the next higher 2^N for a given number
Definition: KSFoundation_host.c:6128
int nover
Definition: KSFoundation.h:1554
int rampsampling
Definition: KSFoundation.h:1553
KS_READ acq
Definition: KSFoundation.h:1549
float fov
Definition: KSFoundation.h:1720
int ramptime
Definition: KSFoundation.h:671
STATUS GEReq_predownload_setrecon_accel(const KS_READTRAP *const readtrap, const KS_PHASER *const phaser, const KS_PHASER *const zphaser, int datadestination)
Sets rh*** variables related to parallel imaging acceleration
Definition: GERequired.e:2318

◆ GEReq_predownload_setrecon_annotations()

void GEReq_predownload_setrecon_annotations ( int  tsp,
int  readdur,
int  time2center,
int  echogap 
)

Sets ih*** variables for TE and rBW annotation

Uses the global UI CVs opnecho, opnex, opte and opte2

Parameters
[in]tspDwell time in [us], i.e. the duration of one sample (which is also 1/rBW)
[in]readdurDuration in [us] of the readout window
[in]time2centerTime in [us] to the center of the echo
[in]echogapGap between two echoes
Returns
void
2771  {
2772 
2773  int duration1, duration2;
2774  int echo_timeoffset2evenecho, echo_timeoffset2oddecho;
2775  int roundinglimit = 40ms;
2776 
2777  /* rBW annotation */
2778  ihvbw1 = 1.0e3 / (tsp * 2.0);
2779  ihvbw2 = ihvbw1;
2780  ihvbw3 = ihvbw1;
2781  ihvbw4 = ihvbw1;
2782  ihvbw5 = ihvbw1;
2783  ihvbw6 = ihvbw1;
2784  ihvbw7 = ihvbw1;
2785  ihvbw8 = ihvbw1;
2786  ihvbw9 = ihvbw1;
2787  ihvbw10 = ihvbw1;
2788  ihvbw11 = ihvbw1;
2789  ihvbw12 = ihvbw1;
2790  ihvbw13 = ihvbw1;
2791  ihvbw14 = ihvbw1;
2792  ihvbw15 = ihvbw1;
2793  ihvbw16 = ihvbw1;
2794 
2795  /* NEX annotation */
2796  ihnex = opnex;
2797 
2798  /* TE */
2799  ihte1 = (opte > roundinglimit) ? ks_calc_roundupms(opte) : opte;
2800 
2801  duration1 = (readdur - time2center) * 2 + echogap; /* 2x (time from k-space center to edge for 1st echo) + additional echo gap */
2802  duration2 = time2center * 2 + echogap; /* 2x (time from start to k-space center for 1st echo) + additional echo gap */
2803 
2804  if ((eeff == 1 && oeff == 0) || (eeff == 0 && oeff == 1) || (acq_type == TYPSPIN)) { /* alternating readout gradient polarity across echoes (like often in GRE), or SpinEcho */
2805  echo_timeoffset2evenecho = duration1; /* between 1 and 2, 3 and 4 etc. */
2806  echo_timeoffset2oddecho = duration2; /* between 2 and 3, 4 and 5 etc. */
2807  } else { /* same readout gradient polarity across echoes */
2808  /* we have a GRE sequence, and there are likely flyback gradients
2809  between each readout to allow for the readout gradient polarity to have the same sign for all echoes */
2810  echo_timeoffset2evenecho = readdur + echogap; /* between 1 and 2, 3 and 4 etc. */
2811  echo_timeoffset2oddecho = readdur + echogap; /* between 2 and 3, 4 and 5 etc. */
2812  }
2813 
2814  if (opnecho == 2) {
2815  if (pite2nub && existcv(opte2) && opte2 > 0) { /* use opte2 if the button is visible and it was selected */
2816  ihte2 = opte2;
2817  } else {
2818  /* partial Fourier note: 2nd readout will have its relative k-space center mirrored */
2819  ihte2 = opte + echo_timeoffset2evenecho;
2820  }
2821  } else if (opnecho > 2) {
2822  int pos = opte + echo_timeoffset2evenecho;
2823  ihte2 = (pos > roundinglimit) ? ks_calc_roundupms(pos) : pos; pos += echo_timeoffset2oddecho;
2824  ihte3 = (pos > roundinglimit) ? ks_calc_roundupms(pos) : pos; pos += echo_timeoffset2oddecho;
2825  ihte4 = (pos > roundinglimit) ? ks_calc_roundupms(pos) : pos; pos += echo_timeoffset2oddecho;
2826  ihte5 = (pos > roundinglimit) ? ks_calc_roundupms(pos) : pos; pos += echo_timeoffset2oddecho;
2827  ihte6 = (pos > roundinglimit) ? ks_calc_roundupms(pos) : pos; pos += echo_timeoffset2oddecho;
2828  ihte7 = (pos > roundinglimit) ? ks_calc_roundupms(pos) : pos; pos += echo_timeoffset2oddecho;
2829  ihte8 = (pos > roundinglimit) ? ks_calc_roundupms(pos) : pos; pos += echo_timeoffset2oddecho;
2830  ihte9 = (pos > roundinglimit) ? ks_calc_roundupms(pos) : pos; pos += echo_timeoffset2oddecho;
2831  ihte10 = (pos > roundinglimit) ? ks_calc_roundupms(pos) : pos; pos += echo_timeoffset2oddecho;
2832  ihte11 = (pos > roundinglimit) ? ks_calc_roundupms(pos) : pos; pos += echo_timeoffset2oddecho;
2833  ihte12 = (pos > roundinglimit) ? ks_calc_roundupms(pos) : pos; pos += echo_timeoffset2oddecho;
2834  ihte13 = (pos > roundinglimit) ? ks_calc_roundupms(pos) : pos; pos += echo_timeoffset2oddecho;
2835  ihte14 = (pos > roundinglimit) ? ks_calc_roundupms(pos) : pos; pos += echo_timeoffset2oddecho;
2836  ihte15 = (pos > roundinglimit) ? ks_calc_roundupms(pos) : pos; pos += echo_timeoffset2oddecho;
2837  ihte16 = (pos > roundinglimit) ? ks_calc_roundupms(pos) : pos;
2838  }
2839 
2840  /* rhte/rhte2 end up in the raw section of the rawdata header (rdb_hdr_te, rdb_hdr_te2)
2841  while opte/opte in the image section (te,te2). For opnecho > 2, the te2 field is sometimes 0, why
2842  we also need to rely on rdb_hdr_te2 for offline reconstruction */
2843  rhte = ihte1;
2844  rhte2 = ihte2;
2845 
2846 
2847  /* Flip Angle */
2848  ihflip = opflip;
2849 
2850 } /* GEReq_predownload_setrecon_annotations() */
int ks_calc_roundupms(int time)
Rounds up a value in [us] to nearest whole [ms]
Definition: KSFoundation_host.c:6142

◆ GEReq_predownload_setrecon_annotations_readtrap()

void GEReq_predownload_setrecon_annotations_readtrap ( KS_READTRAP readtrap,
int  echogap 
)

Sets ih*** variables for TE and rBW annotation based on a KS_READTRAP

This is a wrapper function to GEReq_predownload_setrecon_annotations() using a KS_READTRAP

Parameters
[in]readtrapPointer to KS_READTRAP
[in]echogapGap between two echoes
Returns
void
2865  {
2866 
2867  GEReq_predownload_setrecon_annotations(readtrap->acq.filt.tsp, readtrap->grad.duration, readtrap->time2center, echogap);
2868 
2869 } /* GEReq_predownload_setrecon_annotations_readtrap() */
void GEReq_predownload_setrecon_annotations(int tsp, int readdur, int time2center, int echogap)
Sets ih*** variables for TE and rBW annotation
Definition: GERequired.e:2771
KS_TRAP grad
Definition: KSFoundation.h:1561
FILTER_INFO filt
Definition: KSFoundation.h:843
KS_READ acq
Definition: KSFoundation.h:1549
int duration
Definition: KSFoundation.h:673
int time2center
Definition: KSFoundation.h:1560

◆ GEReq_predownload_setrecon_annotations_readwave()

void GEReq_predownload_setrecon_annotations_readwave ( KS_READWAVE readwave,
int  echogap 
)

Sets ih*** variables for TE and rBW annotation based on a KS_READWAVE

This is a wrapper function to GEReq_predownload_setrecon_annotations() using a KS_READWAVE

Parameters
[in]readwavePointer to KS_READWAVE
[in]echogapGap between two echoes
Returns
void
2884  {
2885 
2886  GEReq_predownload_setrecon_annotations(readwave->acq.filt.tsp, readwave->grad.duration, readwave->time2center, echogap);
2887 
2888 } /* GEReq_predownload_setrecon_annotations_readwave() */
void GEReq_predownload_setrecon_annotations(int tsp, int readdur, int time2center, int echogap)
Sets ih*** variables for TE and rBW annotation
Definition: GERequired.e:2771
int time2center
Definition: KSFoundation.h:1615
KS_WAVE grad
Definition: KSFoundation.h:1604
FILTER_INFO filt
Definition: KSFoundation.h:843
KS_READ acq
Definition: KSFoundation.h:1606
int duration
Definition: KSFoundation.h:747

◆ GEReq_predownload_setrecon_annotations_epi()

void GEReq_predownload_setrecon_annotations_epi ( KS_EPI epi,
int  echogap 
)

Sets ih*** variables for TE and rBW annotation based on a KS_EPI

This is a wrapper function to GEReq_predownload_setrecon_annotations() using a KS_EPI

Parameters
[in]epiPointer to KS_EPI
[in]echogapGap between two EPI trains
Returns
void
2903  {
2904  int maxtime_dephasers = IMax(2, epi->readphaser.duration, epi->blipphaser.grad.duration);
2905  int maxtime_rephasers = IMax(2, epi->readphaser.duration, epi->blipphaser.grad.duration);
2906  int halfkspace_duration = ((epi->read.grad.duration + epi->read_spacing) * epi->etl / 2) - epi->read_spacing / 2;
2907  /* time for extra lines beyond half-kspace for partial Fourier in ky */
2908  int overscan_duration = ((epi->read.grad.duration + epi->read_spacing) * (epi->blipphaser.nover / epi->blipphaser.R)) - epi->read_spacing / 2;
2909  int epiduration, time2center;
2910 
2911  if (opautote == PSD_MINTE) {
2912  epiduration = (maxtime_dephasers + overscan_duration + halfkspace_duration + maxtime_rephasers);
2913  time2center = maxtime_dephasers + overscan_duration;
2914  } else {
2915  epiduration = (maxtime_dephasers + 2 * halfkspace_duration + maxtime_rephasers);
2916  time2center = maxtime_dephasers + halfkspace_duration;
2917  }
2918  GEReq_predownload_setrecon_annotations(epi->read.acq.filt.tsp, epiduration, time2center, echogap);
2919 
2920 
2921 } /* GEReq_predownload_setrecon_annotations_epi() */
int R
Definition: KSFoundation.h:1723
KS_TRAP grad
Definition: KSFoundation.h:1719
void GEReq_predownload_setrecon_annotations(int tsp, int readdur, int time2center, int echogap)
Sets ih*** variables for TE and rBW annotation
Definition: GERequired.e:2771
KS_PHASER blipphaser
Definition: KSFoundation.h:1937
KS_TRAP grad
Definition: KSFoundation.h:1561
int etl
Definition: KSFoundation.h:1941
KS_READTRAP read
Definition: KSFoundation.h:1932
int nover
Definition: KSFoundation.h:1722
KS_TRAP readphaser
Definition: KSFoundation.h:1934
FILTER_INFO filt
Definition: KSFoundation.h:843
int read_spacing
Definition: KSFoundation.h:1942
KS_READ acq
Definition: KSFoundation.h:1549
int duration
Definition: KSFoundation.h:673

◆ GEReq_predownload_setrecon_voldata()

void GEReq_predownload_setrecon_voldata ( int  numvols,
const KS_SLICE_PLAN  slice_plan 
)

Sets rh*** variables related to multi-volume imaging

The combination of rh*** variables allow for 50,000 image planes in GE's database.

However, Pfile data stops writing after 512 planes. To store more than 512 image planes as rawdata, RDS (Raw Data Server) or multivolume Pfiles can be used instead. It is possible that other mechanisms will be available through GE's upcoming Orchestra Live in the future.

Parameters
[in]numvolsNumber of volumes (opfphases)
[in]slice_planThe slice plan (KS_SLICE_PLAN), set up using ks_calc_sliceplan() or similar
Returns
void
2940  {
2941  int numechoes;
2942 
2943  if (numvols < 1)
2944  numvols = 1;
2945 
2946  /* GE's CVs for #slices/TR and #passes (acqs) */
2947  _slquant1.fixedflag = 0;
2948  _acqs.fixedflag = 0;
2949  slquant1 = slice_plan.nslices_per_pass;
2950  acqs = slice_plan.npasses;
2951  /* prescan */
2952  picalmode = 0;
2953  pislquant = slquant1;
2954 
2955  /* rhscnframe and rhpasframe are used when scanning in auto-pass mode w/o specific pass-packets (like GEendpass).
2956  To enable auto-pass mode, set rhtype1 |= RHTYP1AUTOPASS and set these variables to the proper value.
2957  It is unclear how this would work with partial Fourier and ARC, and has not been tested. */
2958  rhscnframe = 0 /* rhnslices*ceil(opnex)*rhdayres */;
2959  rhpasframe = 0 /* slquant1*ceil(opnex)*rhdayres */;
2960  rhtype1 &= ~RHTYP1AUTOPASS; /* diable auto-pass. I.e. require the use of pass packets (which is standard anyway) in scan to dump Pfiles */
2961 
2962  /* raw size */
2963  numechoes = IMax(2, rhnecho, opnecho);
2964  if (!KS_3D_SELECTED) {
2965  rhrawsize = slquant1 * numechoes * (2 * rhptsize) * rhdaxres * rhdayres;
2966  } else {
2967  rhrawsize = opslquant * numechoes * (2 * rhptsize) * rhdaxres * rhdayres;
2968  }
2969 
2970  {
2971  char tmpstr[100];
2972  sprintf(tmpstr, "rhrawsize = %d bytes/channel (KSFoundation)", (int) rhrawsize);
2973  cvdesc(rhrawsizeview, tmpstr);
2974  }
2975 
2976  /* Volumes & total size */
2977  rhnphases = numvols; /* must be = numvols (not numvols*acqs=#pfiles !!)
2978  - if 1 when numvols >1:
2979  Prep Action failed: error please try again. ErrorLog="The integer value for ps_to_rs[0] in the header = 0 "
2980  - if numvols*acqs when acqs > 1 and numvols == 1:
2981  Scan failed (after few secs, no images) */
2982  rhnpasses = rhnphases * slice_plan.npasses; /* must be == # volumes (Pfiles) dumped or system hangs and needs rebooting ! */
2983  rhreps = rhnphases;
2984  if (!KS_3D_SELECTED) {
2985  rhnslices = slice_plan.nslices * rhnphases;
2986  } else {
2987  rhnslices = opslquant * opvquant * rhnphases;
2988  }
2989  rhmphasetype = 0; /* Interleaved multiphase */
2990 
2991  rhtype1 |= RHTYP1BAM0FILL ; /* zerofill BAM for clean Pfiles */
2992  rhformat &= ~RHF_ZCHOP; /* no z chopping by default */
2993  rhformat |= RHF_SINGLE_PHASE_INFO;
2994 
2995 #ifdef REV
2996  /* converts the define REV which is a GITSHA, consisting of 7 hexadecimals (16 base), */
2997  /* to a float and sets rhuser46 accordingly */
2998  char revChar[7];
2999  int revNum;
3000  strncpy(revChar,REV,7);
3001  sscanf(revChar, "%x", &revNum);
3002  rhuser46 = (float) revNum;
3003 #endif
3004 
3005  /* Gradwarp Mode */
3006  rhuser47 = cfgradcoil;
3007 
3008  /* copy useful variables to raw header for recon */
3009  /* rhuser32-35 are reserved for off-line VRGF correction (Karolinska) */
3010  rhuser48 = pitscan; /* scan time */
3011 
3012 } /* GEReq_predownload_setrecon_voldata() */
#define KS_3D_SELECTED
Definition: KSFoundation.h:242
int nslices_per_pass
Definition: KSFoundation.h:1320
int npasses
Definition: KSFoundation.h:1319
int nslices
Definition: KSFoundation.h:1318

◆ GEReq_predownload_setrecon_epi()

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

Calls GEReq_predownload_setrecon_readphase(), GEReq_predownload_setrecon_voldata() and GEReq_predownload_setrecon_annotations_epi(), and GEReq_predownload_genrowflip(). Additionally, some rh*** variables are overridden for EPI.

Parameters
[in]epiPointer to KS_EPI
[in]numvols2storeNumber of volumes to store (including calibration vols such as ghostcorr)
[in]slice_planThe slice plan (KS_SLICE_PLAN) set up using ks_slice_plan() or similar
[in]echogapGap between two EPI trains in [us]
[in]blipsignKS_EPI_POSBLIPS or KS_EPI_NEGBLIPS
[in]datadestinationValue passed on to GEReq_predownload_setrecon_readphase() to set rhexecctrl
[in]multishotflag0: Parallel imaging mode 1: Multishot mode
[in]staticghostcalIntegrated refscan (Nyquist ghost correction). 0:Off, 1:On
[in]imsize_policyChoice between KS_IMSIZE_NATIVE, KS_IMSIZE_POW2, KS_IMSIZE_MIN256
Return values
STATUSSUCCESS or FAILURE
3036  {
3037 
3038  if (datadestination & RHXC_XFER_IM) {
3039  return ks_error("%s: Online recon not supported for KS_EPI data on DV26 or later", __FUNCTION__);
3040  }
3041 
3042  GEReq_predownload_setrecon_readphase(&epi->read, &epi->blipphaser, NULL, imsize_policy, datadestination); /* also sets rhasset when R > 1 */
3043  GEReq_predownload_setrecon_voldata(numvols2store, slice_plan); /* opfphases = number of volumes */
3045 
3046 
3047  /* EPI specific rh* vars */
3048  rhileaves = epi->blipphaser.R;
3049  rhkydir = (blipsign == KS_EPI_POSBLIPS) ? 2 : 0;
3050  rhmphasetype = 0; /* Interleaved multiphase */
3051 
3052  if (multishotflag > 0) {
3053  /* .R for multi-shot. Override values set in GEReq_predownload_setrecon_readphase()->GEReq_predownload_setrecon_accel() */
3054  _rhasset.fixedflag = FALSE;
3055  _rhasset_R.fixedflag = FALSE;
3056  rhasset = 0;
3057  rhasset_R = 1.0;
3058  }
3059 
3060  /* Turn on row-flipping if ETL > 1 */
3061  if (epi->etl > 1) {
3062  rhformat |= RHF_USE_FLIPTABLE;
3063  if (datadestination & RHXC_XFER_IM) {
3064  /* Online recon: Single-shot w/ or w/o ASSET */
3065  GEReq_predownload_genrowflip(epi, blipsign, rhasset, TRUE);
3066  } else {
3067  /* Offline recon, say we do rowflip in rhformat, because otherwise GERecon('EPI.ComputeCoefficients') does not
3068  work (requires RHF_USE_FLIPTABLE to be set).
3069  But let's not set any negative entries in the file for offline use to avoid rowflipping to actually occur:
3070  DV26+: This file is ignored for scan archives
3071  Pre DV26: We don't want the rows to be flipped correctly in the Pfile currently since we don't understand
3072  why the lines are flipped wrong for mulitshot EPI. We deal with rowflipping ourselves in the recon
3073  */
3074  GEReq_predownload_genrowflip(epi, blipsign, rhasset, FALSE);
3075  }
3076  } else {
3077  rhformat &= ~RHF_USE_FLIPTABLE;
3078  }
3079 
3080  /* fermi filter */
3081  rhfermr = opxres/2;
3082 
3083 
3084  /* override flip control set in GEReq_predownload()->{@inline loadrheader.e rheaderinit} */
3085  eepf = 0;
3086  eeff = 0;
3087  oepf = 0;
3088  oeff = 0;
3089  set_echo_flip(&rhdacqctrl, &chksum_rhdacqctrl, eepf, oepf, eeff, oeff); /* clear bit 1 - flips image in phase dir */
3090 
3091  rhdacqctrl |= 8192; /* disable Orchestra recon */
3092 
3093  /* save echo spacing value into rhesp */
3094  rhesp = epi->read.grad.duration;
3095 
3096 
3097 
3098  /* default but see below */
3099  rhpctemporal = 1;
3100  rhpccoil = 0;
3101  rhref = (staticghostcal) ? 5 : 0;
3102 
3103  /* Diffusion or not */
3104  if (opdiffuse || optensor) {
3105  rhtype1 |= RHTYP1DIFFUSIONEPI;
3106  } else {
3107  rhtype1 &= ~RHTYP1DIFFUSIONEPI;
3108  }
3109 
3110  return SUCCESS;
3111 
3112 } /* GEReq_predownload_setrecon_epi() */
int R
Definition: KSFoundation.h:1723
int opxres
void GEReq_predownload_setrecon_readphase(const KS_READTRAP *const readtrap, const KS_PHASER *const phaser, const KS_PHASER *const zphaser, int imsize_policy, int datadestination)
Sets required global rh*** variables for Cartsian imaging
Definition: GERequired.e:2633
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
KS_PHASER blipphaser
Definition: KSFoundation.h:1937
STATUS GEReq_predownload_genrowflip(KS_EPI *epi, int blipsign, int assetflag, int dorowflip)
Generates the rowflip.param file for KS_EPI
Definition: GERequired.e:1598
KS_TRAP grad
Definition: KSFoundation.h:1561
int etl
Definition: KSFoundation.h:1941
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
void GEReq_predownload_setrecon_voldata(int numvols, const KS_SLICE_PLAN slice_plan)
Sets rh*** variables related to multi-volume imaging
Definition: GERequired.e:2940
Definition: KSFoundation.h:2330
int duration
Definition: KSFoundation.h:673

◆ GEReq_predownload_prescan_options()

STATUS GEReq_predownload_prescan_options ( RG_CAL_MODE_E  rg_cal_mode)

Prescan options

Parameters
[in]rg_cal_modeRG_CAL_MODE_E
Return values
STATUSSUCCESS or FAILURE
3124  {
3125 
3126  /* cvoverride(psd_pscall, -1, PSD_FIX_ON, PSD_EXIST_ON); */ /* disable all prescan? */
3127 
3128  /* Transmit Gain (TG) Auto always */
3129  cvoverride(psd_psctg, 0, PSD_FIX_ON, PSD_EXIST_ON); /* 0: Auto TG */
3130  pidotg = psd_psctg;
3131 
3132 
3133 #if EPIC_RELEASE > 26
3134  /* Gradient shim. Stop sequence specific overrides from Prescan.e so Shim menu reflects what is going
3135  to happen, regardless of EPI/diffusion modes */
3136  opgradshim = 2; /* Grad Shim (Auto). Default, will be changed by Shim menu */
3137  if (opgradshim == 2) { /* Auto */
3138  cvoverride(psd_pscshim, 0, PSD_FIX_ON, PSD_EXIST_ON);
3139  } else if (opgradshim == 1) { /* Force ON */
3140  cvoverride(psd_pscshim, 1, PSD_FIX_ON, PSD_EXIST_ON);
3141  } else if (opgradshim == 0) { /* Force OFF */
3142  cvoverride(psd_pscshim, -1, PSD_FIX_ON, PSD_EXIST_ON);
3143  }
3144  pidoshim = psd_pscshim;
3145 #endif
3146 
3147  /* Receive gain (R1/R2) control:
3148  epic_ui_control.h:
3149  typedef enum RG_CAL_MODE {
3150  RG_CAL_MODE_MIN = 0,
3151  RG_CAL_MODE_MEASURED = 0,
3152  RG_CAL_MODE_HIGH_FIXED = 1,
3153  RG_CAL_MODE_LOW_FIXED = 2,
3154  RG_CAL_MODE_AUTO = 3,
3155  RG_CAL_MODE_MAX = 3
3156  } RG_CAL_MODE_E;
3157  */
3158  cvoverride(oprgcalmode, rg_cal_mode, PSD_FIX_ON, PSD_EXIST_ON);
3159 
3160  return SUCCESS;
3161 
3162 } /* GEReq_predownload_prescan_options() */

◆ GEReq_cvinit()

STATUS GEReq_cvinit ( void  )

Helper function to be called at the beginning of cvinit()

In the beginning of cvinit() the following lines should be added:

STATUS status = GEReq_cvinit();
KS_RAISE(status);

This function sets up various global GE stuff, including e.g. the gradient specs. The gradient specs are controlled by ks_srfact and ks_qfact. ks_srfact Should have a value that will allow scanning on all MR systems without PNS effects. Also, ks_srfact does not affect the EPI train in ksepi.e, since it controls the slewrate and gradient max separately. ks_qfact is supposed to be 1 by default, with the purpose to from an optimal setting reduce the slewrate to reduce the acoustic noise. A default value of 1.0 will make the system perform best but with high acoustic noise. A value of about 8-10 may be a good trade-off between acoustic noise reduction and reasonable image quality.

In this function, ks_sarcheckdone is set to FALSE. This CV is checked in GEReq_predownload() and ks_pg_rf(), which both will complain if it is not has been set to TRUE. GEReq_eval_checkTR_SAR_calcs() sets this CV to TRUE.

It is important that an error returned from GEReq_cvinit() also results in an error in cvinit(), otherwise it will not show up in the UI.

Return values
STATUSSUCCESS or FAILURE
3194  {
3195 
3196  /* ART: Acoustic noise reduction
3197  Imaging option button "Acoustic reduction":
3198  - PSD_IOPT_MILDNOTE in sequence_iopts[]
3199  - Sets CV opsilent = TRUE
3200  When acoustic noise reduction (ART) imaging option is checked, enable the ART tab in the UI too
3201  by forcing cfnumartlevels = 2
3202  - "Moderate" radio button on ART tab: CV opsilentlevel = 1
3203  - "High" radio button on ART tab: CV opsilentlevel = 2
3204  */
3205  cvoverride(cfnumartlevels, 2, PSD_FIX_OFF, PSD_EXIST_ON);
3206  pinumartlevels = cfnumartlevels;
3207 
3208 #if EPIC_RELEASE >= 28
3209  /* always derate slewrate for cal scan (Prescan.e) if < 5.0 */
3210  if (cal_sr_derate < 5.0) {
3211  cvoverride(cal_sr_derate, 5.0, PSD_FIX_ON, PSD_EXIST_ON);
3212  }
3213 #endif
3214 
3215  if (opsilent) {
3216  _ks_qfact.existflag = TRUE;
3217  if (opsilentlevel == 1) {
3218  /* moderate */
3219  ks_qfact = 3.0;
3220 #if EPIC_RELEASE >= 28
3221  cvoverride(cal_sr_derate, 15.0, PSD_FIX_ON, PSD_EXIST_ON);
3222 #endif
3223  } else {
3224  /* high */
3225  ks_qfact = 6.0;
3226 #if EPIC_RELEASE >= 28
3227  cvoverride(cal_sr_derate, 15.0, PSD_FIX_ON, PSD_EXIST_ON);
3228 #endif
3229  }
3230  } else {
3231  ks_qfact = 1.0;
3232  }
3233 
3234 
3235  {
3236 
3237 
3238  }
3239 
3240  EpicConf();
3241 
3242  /* set gradient limitations (calling GEs obloptimize() & further ramptime modifications) */
3244 
3245  /* resets all filter #. From this point, ok to call setfilter() */
3246  initfilter();
3247 
3248  /* setsysparams() sets psd_grd_wait and psd_rf_wait for the system */
3249  setsysparms();
3250 #ifdef SIM
3251  /* In simulation, we don't want them to confuse the timing in WTools */
3252  _psd_grd_wait.fixedflag = 0;
3253  _psd_rf_wait.fixedflag = 0;
3254  psd_grd_wait = 0;
3255  psd_rf_wait = 0;
3256 #endif
3257 
3258 #include "cvinit.in" /* Runs the code generated by macros in preproc.*/
3259 
3260  /* GE CVs that could use a wider min/max range: */
3261  cvmax(rhfrsize, 32768);
3262  cvmax(rhdaxres, 32768);
3263  cvmax(opphasefov, 5); /* to allow larger FOV in phase enc dir that freq */
3264  cvmax(rhnslices, 50000); /* 50,000, which is 5x of RHF_MAX_IMAGES_MULTIPHASE = 10000 */
3265  cvmax(rhreps, 2048); /* max 2048 vols */
3266  cvmax(rhnphases, 2048); /* max 2048 vols */
3267  cvmax(opfphases, 2048); /* max 2048 vols */
3268  cvmax(opyres, 1024); /* max 1024 yres */
3269  cvmax(opslthick, 200); /* max 200 mm slice thickness */
3270  cvmax(optr, 60s); /* max 60s TR */
3271  cvmax(ihtr, 60s);
3272  cvmax(rhref, 5); /* Allow 1st-volume ghost correction as GE's diffusion EPI (only works for single shot) */
3273  cvmax(opbval, 30000);
3274  cvmax(opileave, 1);
3275 
3276 #if EPIC_RELEASE > 29 || (EPIC_RELEASE == 29 && EPIC_SUBRELEASE == 1)
3277  cvset(opzres, 0, 100, 100, "");
3278  setexist(opzres, TRUE);
3279 #endif
3280 
3281  /* activate Advisory panel */
3282  piadvise = PSD_ON;
3283  piadvmin = (1 << PSD_ADVTE); /* TE Advisory on */
3284  piadvmin |= (1 << PSD_ADVTR); /* TR Advisory on */
3285  piadvmin |= (1 << PSD_ADVRCVBW);/* rBW Advisory on */
3286  piadvmin |= (1 << PSD_ADVFOV);/* FOV Advisory on */
3287  piadvmax = piadvmin;
3288 
3289  {
3290 
3291 
3292  }
3293 
3294  /* KSFoundation indicator variable for completed SAR checks (c.f. GEReq_eval_checkTR_SAR_calcs(), which sets it to TRUE) */
3295  ks_sarcheckdone = FALSE;
3296 
3297  /* GE's psd_name seems not be available on TGT, to let's copy this one */
3298 #if EPIC_RELEASE >= 27
3299  /* Since RX27R02, GE's psd_name no longer exists */
3300  {
3301  strcpy(ks_psdname, get_psd_name());
3302  }
3303 #else
3304  strcpy(ks_psdname, psd_name);
3305 #endif
3306 
3307 #if EPIC_RELEASE > 29 || (EPIC_RELEASE == 29 && EPIC_SUBRELEASE == 1)
3308  pizresnub = 0; /* 3D Don't show slice res menu by default */
3309 #endif
3310 
3311  /* populate a global KS_SEQ_CONTROL for pass packet. Used to make TR timing sum up correctly */
3314  strcpy(seqctrl_passpack.description, "passpack");
3315 
3316  return SUCCESS;
3317 
3318 } /* GEReq_cvinit() */
int opyres
STATUS GEReq_init_gradspecs(LOG_GRAD *loggrd, PHYS_GRAD *phygrd, float srfact)
Initialize logical and physical gradient specifications
Definition: GERequired.e:435
PHYS_GRAD phygrd
int duration
Definition: KSFoundation.h:1227
KS_SEQ_CONTROL seqctrl_passpack
Definition: GERequired.e:248
char ks_psdname[256]
Definition: GERequired.e:245
float ks_qfact
Definition: GERequired.e:271
LOG_GRAD loggrd
int min_duration
Definition: KSFoundation.h:1224
#define cvset(cv, min, max, def, desc)
Definition: KSFoundation.h:2380
int pw_passpacket
Definition: GERequired.e:266
int ks_sarcheckdone
Definition: GERequired.e:243
int psd_grd_wait
KS_DESCRIPTION description
Definition: KSFoundation.h:1234
int psd_rf_wait
float opslthick
float ks_srfact
Definition: GERequired.e:270

◆ GEReq_cveval()

STATUS GEReq_cveval ( void  )

Helper function to be called at the beginning of cveval()

In the beginning of cveval() the following lines should be added:

STATUS status = GEReq_cveval();
KS_RAISE(status);

This function up various global GE stuff, and copies also the struct array scan_info, holding the prescribed slice locations to ks_scan_info, the latter which can also be accessible on TGT.

Simulation (WTools): If we have ks_simscan = 1 (default), simscan() will have make up slice locations in ks_scan_info based on opslthick, opslspace and opslquant. Note, GE clears scan_info between cvcheck() and predownload() when in simulation. Hence, we now have the opposite case, i.e. we have some slice info data in ks_scan_info but nothing in scan_info.

It is important that an error returned from GEReq_cveval() also results in an error in cveval(), otherwise it will not show up in the UI.

Return values
STATUSSUCCESS or FAILURE
3346  {
3347 
3348  {
3349 
3350 
3351  }
3352 
3353  InitAdvPnlCVs();
3354 
3355 
3356 #if EPIC_RELEASE > 29 || (EPIC_RELEASE == 29 && EPIC_SUBRELEASE == 1)
3357  rhacqslthick = opslthick;
3358 #endif
3359 
3360 #ifdef PSD_HW
3361  /* MR scanner (hardware): copy scan_info to ks_scan_info, so we can use this data on TGT */
3362  memcpy(ks_scan_info, scan_info, opslquant*sizeof(SCAN_INFO));
3363 #else
3364  /* WTools (sim) */
3365  if (ks_simscan)
3366  simscan();
3367 #endif
3368 
3369  return SUCCESS;
3370 
3371 } /* GEReq_cveval() */
STATUS simscan(void)
Simulate scan locations in simulation (WTools)
Definition: GERequired.e:340
SCAN_INFO scan_info[]
float opslthick
int ks_simscan
Definition: GERequired.e:269
endif SCAN_INFO ks_scan_info[SLTAB_MAX]
Definition: GERequired.e:240

◆ getAPxParam()

void getAPxParam ( optval *  min,
optval *  max,
optdelta *  delta,
optfix *  fix,
float  coverage,
int  algorithm 
)

Mandatory APx functions for PSDs from DV26

DV26 requires getAPxAlgorithm() and getAPxParam() functions to exist in each PSD. Empty getAPxAlgorithm() and getAPxParam() functions are declared below in GERequired.e to allow compilation on DV26. If a PSD wants to use this new functionality in DV26 it should add the following line: #define KS_PSD_USE_APX 1 in its @global section, so that KS_PSD_USE_APX is not set to 0 here, and hence getAPxAlgorithm() and getAPxParam() wont be redeclared here in GERequired.e.

3395  {
3396  /* Need to be filled when APx is supported in this PSD */
3397 }

◆ getAPxAlgorithm()

int getAPxAlgorithm ( optparam *  optflag,
int *  algorithm 
)
3402  {
3403  return APX_CORE_NONE;
3404 
3405 } /* getAPxAlgorithm() */

◆ GEReq_cvcheck()

STATUS GEReq_cvcheck ( void  )

Helper function to be called at the beginning of cvcheck()

In the beginning of cvcheck() the following lines should be added:

STATUS status = GEReq_cveval();
KS_RAISE(status);

It is important that an error returned from GEReq_cvcheck() also results in an error in cvcheck(), otherwise it will not show up in the UI.

Return values
STATUSSUCCESS or FAILURE
3430  {
3431 
3432  if (existcv(opslspace) && existcv(opslthick) && (opslspace < 0) && (opslthick <= fabs(opslspace))) {
3433  return KS_THROW("Slice overlap must be less than %.2f mm", opslthick);
3434  }
3435  if (existcv(optr) && optr < avmintr) {
3436  return KS_THROW("The minimum TR is %-d ms", (avmintr / 1ms));
3437  }
3438  if (existcv(optr) && optr > avmaxtr) {
3439  return KS_THROW("The maximum TR is %-d ms", (avmaxtr / 1ms));
3440  }
3441  if ((exist(opte) < avminte) && existcv(opte)) {
3442  return KS_THROW("The minimum TE is %-d ms", (avminte / 1ms));
3443  }
3444  if ((exist(opte) > avmaxte) && existcv(opte)) {
3445  return KS_THROW("The maximum TE is %-d ms", (avmaxte / 1ms));
3446  }
3447 
3448  return SUCCESS;
3449 
3450 } /* GEReq_cvcheck() */
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
float opslthick

◆ GEReq_predownload()

STATUS GEReq_predownload ( void  )

Helper function to be called at the beginning of predownload()

In the beginning of predownload() the following lines should be added:

STATUS status = GEReq_predownload();
KS_RAISE(status);

This function up various global GE stuff related to recon and data filters. Also, ks_sarcheckdone is checked to make sure that GEReq_eval_checkTR_SAR_calcs() has been called to monitor SAR/heating limits.

It is important that an error returned from GEReq_predownload() also results in an error in predownload(), otherwise it will not show up in the UI.

Return values
STATUSSUCCESS or FAILURE
3473  {
3474 
3475  {
3476  }
3477 
3478  nex = ceil(opnex); /* nex is used in rheaderinit instead of opnex, so must set it here. otherwise prescan fails */
3479 
3480 
3481  /* UsePgenOnHost() (Imakefile) likes calling calcPulseParams() at this spot, containing "predownload.in" */
3482  calcPulseParams(0);
3483 
3484  {
3485 
3486 
3487  /* the compiler flag "MINIMIZE_PSFILTERS" will try to minimize the number of filter slots used in precan, sum code from prescan.e will be replaced */
3488  if (ks_compress_ps_filter_slots == TRUE){
3489 
3491 
3492  } else {
3493 
3494 
3495  }
3496 
3497 
3498 
3499 
3500  }
3501 
3502  /* Set rhkacq_uid for ARC support and linking plots */
3503  int uid;
3504  struct tm now;
3505  time_t now_epoch = time(NULL);
3506  /* Generate unique ID for this scan for naming kacq files and
3507  debug files. Use the current date and time (MMDDHHMMSS).
3508  Cannot include the year because this is larger than a
3509  signed 32-bit integer */
3510  localtime_r(&now_epoch, &now);
3511  uid = now.tm_sec +
3512  now.tm_min * 100 +
3513  now.tm_hour * 10000 +
3514  now.tm_mday * 1000000 +
3515  (now.tm_mon + 1) * 100000000;
3516  rhkacq_uid = uid;
3517 
3518  /* Check that SAR calculations have been performed */
3519  if (ks_sarcheckdone != TRUE) {
3520 #ifdef SIM
3521  if (existcv(optr) == TRUE && existcv(opte) == TRUE && existcv(opslquant) == TRUE) {
3522  /* In simulation (WTools), predownload is called every time a CV is changed but
3523  ks_sarcheckdone will not be set to TRUE in GEReq_eval_checkTR_SAR_calcs() unless
3524  optr, opte and opslquant have all been set (existcv() != FALSE). Hence, in simulation,
3525  we cannot throw an error before these have been set */
3526  return ks_error("%s: Missing call to GEReq_eval_checkTR_SAR()", __FUNCTION__);
3527  }
3528 #else
3529  return ks_error("%s: Missing call to GEReq_eval_checkTR_SAR()", __FUNCTION__);
3530 #endif
3531  }
3532 
3533  return SUCCESS;
3534 
3535 } /* GEReq_predownload() */
STATUS GEReq_predownload_minimize_ps_filter_slots()
Definition: GERequired.e:1416
STATUS ks_error(const char *format,...) __attribute__((format(printf
Common error message function for HOST and TGT
STATUS calcPulseParams(int p)
Mandatory GE function. Includes predownload.in
Definition: GERequired.e:323
int ks_compress_ps_filter_slots
Definition: GERequired.e:274
int rhkacq_uid
int ks_sarcheckdone
Definition: GERequired.e:243

◆ GEReq_pulsegenBegin()

void GEReq_pulsegenBegin ( void  )

Helper function to be called at the beginning of pulsegen()

In the beginning of pulsegen() the following lines should be added:

This function up various global GE stuff related to pulsegen()

3571  {
3572 
3573  sspinit(psd_board_type);
3574 
3575  {
3576 
3577 
3578  }
3579 
3580 } /* GEReq_pulsegenBegin() */

◆ GEReq_pulsegenEnd()

void GEReq_pulsegenEnd ( void  )

Helper function to be called at the end of pulsegen()

In the end of pulsegen(), but before buildinstr(), the following lines should be added:

This function up prescan pulsegen and adds a PASSPACK sequence ("GEendpass"), which is used to dump rawdata and mark the end of scan. See GEReq_endofpass() and GEReq_endofscan() and how they are used in a psd.

3598  {
3599 
3600 #ifdef IPG
3601  {
3602  }
3603 
3604 PASSPACK(GEendpass, pw_passpacket-1ms);
3605 SEQLENGTH(GEpass, pw_passpacket, GEpass);
3606 
3607 #endif
3608 
3609 } /* GEReq_pulsegenEnd() */
int pw_passpacket
Definition: GERequired.e:266

◆ GEReq_endofpass()

int GEReq_endofpass ( )

Sets SSP word in sequence off_GEpass() to trigger data (Pfile) writing and reconstruction

After calling this function, the parent function must switch back to the previous/main sequence using ks_scan_playsequence() (or boffset()).

3621  {
3622 #ifdef IPG
3623  boffset(off_GEpass);
3624  setwamp(SSPD + DABPASS, &GEendpass, 2 ); /* end of pass */
3625  startseq(0, (short) MAY_PAUSE);
3626 #else
3627  /* HOST */
3629 
3630  KS_DESCRIPTION slicegroup_desc;
3631  sprintf(slicegroup_desc, "endofpass");
3633 
3635 #endif
3636  return pw_passpacket;
3637 
3638 } /* GEReq_endofpass() */
STATUS startseq(s16, s16)
#define KS_NOTSET
Definition: KSFoundation.h:115
STATUS boffset(long *offsets)
KS_SEQ_CONTROL seqctrl_passpack
Definition: GERequired.e:248
int nseqinstances
Definition: KSFoundation.h:1225
Definition: KSFoundation.h:403
int pw_passpacket
Definition: GERequired.e:266
void ks_plot_slicetime_endofslicegroup_tagged(const char *desc, const KS_PLOT_SLICEGROUP_MODE tag)
ADDTITLEHERE
Definition: KSFoundation_common.c:4296
Definition: KSFoundation.h:414
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
char KS_DESCRIPTION[KS_DESCRIPTION_LENGTH]
Definition: KSFoundation.h:351

◆ GEReq_endofscan()

int GEReq_endofscan ( )

Sets SSP word in sequence off_GEpass() to tell system that scan is done

3647  {
3648 #ifdef IPG
3649  boffset(off_GEpass);
3650  setwamp(SSPD + DABSCAN, &GEendpass, 2 ); /* end of scan */
3651  startseq(0, (short) MAY_PAUSE);
3652 #else
3653  /* HOST */
3654  strcpy(seqctrl_passpack.description, "passpack_endofscan");
3656 
3657  KS_DESCRIPTION slicegroup_desc;
3658  sprintf(slicegroup_desc, "endofscan");
3660 
3662  strcpy(seqctrl_passpack.description, "passpack");
3663 #endif
3664  return pw_passpacket;
3665 
3666 } /* GEReq_endofscan() */
STATUS startseq(s16, s16)
#define KS_NOTSET
Definition: KSFoundation.h:115
STATUS boffset(long *offsets)
KS_SEQ_CONTROL seqctrl_passpack
Definition: GERequired.e:248
int nseqinstances
Definition: KSFoundation.h:1225
Definition: KSFoundation.h:403
int pw_passpacket
Definition: GERequired.e:266
void ks_plot_slicetime_endofslicegroup_tagged(const char *desc, const KS_PLOT_SLICEGROUP_MODE tag)
ADDTITLEHERE
Definition: KSFoundation_common.c:4296
Definition: KSFoundation.h:414
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
KS_DESCRIPTION description
Definition: KSFoundation.h:1234
char KS_DESCRIPTION[KS_DESCRIPTION_LENGTH]
Definition: KSFoundation.h:351

◆ GEReq_endofpassandscan()

int GEReq_endofpassandscan ( )

Sets SSP word in sequence off_GEpass() to tell system that scan is done

3675  {
3676  #ifdef IPG
3677  boffset(off_GEpass);
3678  setwamp(SSPD + DABPASS + DABSCAN, &GEendpass, 2 ); /* end of scan */
3679  startseq(0, (short) MAY_PAUSE);
3680  #else
3681  /* HOST */
3682  strcpy(seqctrl_passpack.description, "passpack_endofpassandscan");
3684 
3685  KS_DESCRIPTION slicegroup_desc;
3686  sprintf(slicegroup_desc, "endofpassandscan");
3688 
3690  strcpy(seqctrl_passpack.description, "passpack");
3691  #endif
3692  return pw_passpacket;
3693 
3694 } /* GEReq_endofpassandscan() */
STATUS startseq(s16, s16)
#define KS_NOTSET
Definition: KSFoundation.h:115
STATUS boffset(long *offsets)
KS_SEQ_CONTROL seqctrl_passpack
Definition: GERequired.e:248
int nseqinstances
Definition: KSFoundation.h:1225
Definition: KSFoundation.h:403
int pw_passpacket
Definition: GERequired.e:266
void ks_plot_slicetime_endofslicegroup_tagged(const char *desc, const KS_PLOT_SLICEGROUP_MODE tag)
ADDTITLEHERE
Definition: KSFoundation_common.c:4296
Definition: KSFoundation.h:414
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
KS_DESCRIPTION description
Definition: KSFoundation.h:1234
char KS_DESCRIPTION[KS_DESCRIPTION_LENGTH]
Definition: KSFoundation.h:351

◆ dummylinks()

void dummylinks ( void  )

Not sure what this function does, but it exists in all product psds.

3761  {
3762  epic_loadcvs( "thefile" ); /* for downloading CVs */
3763 
3764 } /* dummylinks() */

◆ GEReq_initRSP()

void GEReq_initRSP ( void  )

RSP Init. To be inserted in the psdinit() function (or scan()) in the main sequence

3773  {
3774 
3775  /* Initialize everything to a known state */
3776  setrfconfig((short) ks_rfconf); /* ENBL_RHO1 + ENBL_THETA + ENBL_OMEGA + ENBL_OMEGA_FREQ_XTR1 = 141 */
3777  rspqueueinit(200); /* Initialize to 200 entries */
3778  syncoff(&GEpass); /* Deactivate sync during pass */
3779 
3780 } /* GEReq_initRSP() */
int ks_rfconf
Definition: GERequired.e:268

Variable Documentation

◆ rfpulseInfo

RF_PULSE_INFO rfpulseInfo[RF_FREE] = { {0, 0} }

◆ avail_image_time

int avail_image_time

◆ act_tr

ifndef ACT_TR_EXISTS int act_tr

◆ ks_scan_info

endif SCAN_INFO ks_scan_info[SLTAB_MAX] = {DEFAULT_AXIAL_SCAN_INFO}

N.B.: this file should contain includes and definitions common for host, target and sim that are private to KSFoundation. If in doubt always try to add here first instead of KSFoundation.h since that contains the public interface.

◆ ks_slice_plan

◆ ks_sarcheckdone

int ks_sarcheckdone = FALSE

◆ ks_psdname

char ks_psdname[256]

◆ ks_perform_slicetimeplot

int ks_perform_slicetimeplot = FALSE

◆ seqctrl_passpack

KS_SEQ_CONTROL seqctrl_passpack = KS_INIT_SEQ_CONTROL

◆ obl_debug

int obl_debug = 0 with {0, 1, 0, INVIS, "On(=1) to print messages for obloptimize",}

◆ obl_method

int obl_method = PSD_OBL_OPTIMAL with {PSD_OBL_RESTRICT, PSD_OBL_OPTIMAL, PSD_OBL_OPTIMAL, INVIS, "On(=1) to optimize the targets based on actual rotation matrices",}

◆ filter_echo1

int filter_echo1 = 0 with {, , , INVIS, "Scan filter slot number needed for prescan",}

◆ pw_passpacket

int pw_passpacket = 50ms with {10ms, 1000ms, 50ms, VIS, "Duration of the passpacket sequence",}

◆ ks_rfconf

int ks_rfconf = ENBL_RHO1 + ENBL_THETA + ENBL_OMEGA + ENBL_OMEGA_FREQ_XTR1

◆ ks_simscan

int ks_simscan = 1 with {0, 1, 1, VIS, "Simulate slice locations if 1 (and in simulation)",}

◆ ks_srfact

float ks_srfact = 1.0 with {0.01, 3.0, 1.0, VIS, "Slewrate factor (low value = slower gradients)",}

◆ ks_qfact

float ks_qfact = 1.0 with {0.1, 40.0, 1.0, VIS, "Quietness factor",}

◆ ks_plot_filefmt

int ks_plot_filefmt = KS_PLOT_MAKEPNG with {KS_PLOT_OFF,KS_PLOT_MAKEPNG,KS_PLOT_MAKEPNG, VIS, "Plot format 0:off 1:PDF 2:SVG 3:PNG"}

◆ ks_plot_kstmp

int ks_plot_kstmp = FALSE with {FALSE,TRUE,FALSE, VIS, "0: off 1:Copy plots to mrraw/kstmp"}

◆ ks_compress_ps_filter_slots

int ks_compress_ps_filter_slots = FALSE with {FALSE,TRUE,FALSE, VIS, "Minimize the number of filterslots for prescan"}

◆ ks_clinicalmode

int ks_clinicalmode = CLINICAL_MODE with {0, 1, CLINICAL_MODE, VIS, "Clinical mode: on=1 / off=0"}

◆ maxB1

float maxB1[MAX_ENTRY_POINTS]

◆ maxB1Seq

float maxB1Seq

◆ debugstate

short debugstate

◆ viewtable

short viewtable[513]

◆ psdexitarg

PSD_EXIT_ARG psdexitarg

◆ rspent

int rspent

◆ rspdda

int rspdda

◆ rspbas

int rspbas

◆ rspvus

int rspvus

◆ rspgy1

int rspgy1

◆ rspasl

int rspasl

◆ rspesl

int rspesl

◆ rspchp

int rspchp

◆ rspnex

int rspnex

◆ rspslq

int rspslq

◆ rspsct

int rspsct

◆ rsprep

int rsprep

◆ chopamp

short chopamp

◆ seqCount

int seqCount

◆ view

int view

◆ excitation

int excitation

◆ debug

int debug

◆ entry_name_list

const CHAR* entry_name_list[ENTRY_POINT_MAX]
Initial value:
= {
"scan",
"mps2",
"aps2",
}