KSFoundation  [October2024]
A platform for structured EPIC programming on GE MR systems
Sequence-independent looping functions (ksscan.h)

Data Structures

struct  KS_SLICETIMING_DESIGN
 
struct  KS_SLICETIMING
 
struct  KS_CORESLICETIME
 
struct  KS_PHASEENCODING_PLAN_DESIGN
 
struct  KSSCAN_LOOP_CONTROL
 
struct  KSSCAN_LOOP_CONTROL_DESIGN
 

Macros

#define KS_MAX_RF_SCANINFO   256
 
#define KS_INIT_SLICETIMING_DESIGN   {KS_INITVALUE(SLTAB_MAX, DEFAULT_AXIAL_SCAN_INFO), KS_NOTSET, 0, 1, 1, 2, 0, 0}
 
#define KS_INIT_SLICETIMING   {KS_INITVALUE(KS_MAX_RF_SCANINFO, DEFAULT_AXIAL_SCAN_INFO), KS_INIT_SLICEPLAN, KS_NOTSET, KS_NOTSET, 0, 1, 0, SMS_SLICE_ENCODING_DIRECTION_NEG}
 
#define KS_INIT_CORESLICETIME   {0, KS_NOTSET};
 
#define KS_INIT_PHASEENCODING_PLAN_DESIGN   {KS_INIT_DESC, KS_INIT_KSPACE_ACQ, {CARTESIAN_COORD, CARTESIAN_COORD}, 1, KS_NOTSET, MTF_Y, Y_Z, SPLIT_SHOTS_LCPO, KS_INIT_PHASEENCODING_REPEAT_DESIGN}
 
#define KSSCAN_INIT_LOOP_CONTROL   {0, 0, 0, 0, 0, KS_INIT_PHASEENCODING_PLAN, KS_INIT_PHASEENCODING_PLAN, KS_INIT_SLICETIMING}
 
#define KSSCAN_INIT_LOOP_CONTROL_DESIGN   {0, 1, 1, 1, 0, KS_INIT_PHASEENCODING_PLAN_DESIGN, KS_INIT_PHASEENCODING_PLAN_DESIGN, KS_INIT_SLICETIMING_DESIGN}
 

Enumerations

enum  SMS_SLICE_ENCODING_DIRECTION { SMS_SLICE_ENCODING_DIRECTION_POS, SMS_SLICE_ENCODING_DIRECTION_NEG }
 

Functions

STATUS ksscan_validate_slicetimingdesign (const KS_SLICETIMING_DESIGN *design)
 
STATUS ksscan_slicetiming_eval_design (KS_SLICETIMING *slicetiming, KS_SEQ_CONTROL *sequence_to_inflate, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), const KS_SLICETIMING_DESIGN *slicetiming_design)
 
void ksscan_copy_slices (KS_SLICETIMING_DESIGN *slicetiming_design, const SCAN_INFO *slice_pos)
 
STATUS ksscan_eval_setup_rf_slices (KS_SLICETIMING *slicetiming, const KS_SLICETIMING_DESIGN *slicetiming_design, int is2D)
 
STATUS ksscan_phaseencoding_plan_eval_design (KS_PHASEENCODING_PLAN *pe_plan, const KS_PHASEENCODING_PLAN_DESIGN *design)
 
STATUS ksscan_loop_control_eval_design (KSSCAN_LOOP_CONTROL *loop_control, KS_SEQ_CONTROL *sequence_to_inflate, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), const KSSCAN_LOOP_CONTROL_DESIGN *design)
 
s64 ksscan_sliceloop (const KSSCAN_LOOP_CONTROL *loop_control, KS_DYNAMIC_STATE *dynamic, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
 
s64 ksscan_acqloop (const KSSCAN_LOOP_CONTROL *loop_control, KS_DYNAMIC_STATE *dynamic, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
 
void ksscan_plotloop_shots (const KSSCAN_LOOP_CONTROL *loop_control, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
 
void ksscan_plotloop_slices (const KSSCAN_LOOP_CONTROL *loop_control, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
 
s64 ksscan_scanloop (const KSSCAN_LOOP_CONTROL *orig_loop_control, KS_DYNAMIC_STATE *dynamic, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
 
void ksscan_prescanloop (const KSSCAN_LOOP_CONTROL *loop_control, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), int nloops, int dda)
 
void ksscan_init_loopcontrol (KSSCAN_LOOP_CONTROL *loop_control)
 
void ksscan_init_slicetiming (KS_SLICETIMING *slicetiming)
 
void ks_plot_psd (const KS_SEQ_CONTROL *ctrl, const KSSCAN_LOOP_CONTROL *loopctrl)
 

Detailed Description

Macro Definition Documentation

◆ KS_MAX_RF_SCANINFO

#define KS_MAX_RF_SCANINFO   256

max RF slices per sequence module (2D: num slices, 3D: 1)

◆ KS_INIT_SLICETIMING_DESIGN

#define KS_INIT_SLICETIMING_DESIGN   {KS_INITVALUE(SLTAB_MAX, DEFAULT_AXIAL_SCAN_INFO), KS_NOTSET, 0, 1, 1, 2, 0, 0}

◆ KS_INIT_SLICETIMING

◆ KS_INIT_CORESLICETIME

#define KS_INIT_CORESLICETIME   {0, KS_NOTSET};

◆ KS_INIT_PHASEENCODING_PLAN_DESIGN

◆ KSSCAN_INIT_LOOP_CONTROL

#define KSSCAN_INIT_LOOP_CONTROL   {0, 0, 0, 0, 0, KS_INIT_PHASEENCODING_PLAN, KS_INIT_PHASEENCODING_PLAN, KS_INIT_SLICETIMING}

◆ KSSCAN_INIT_LOOP_CONTROL_DESIGN

#define KSSCAN_INIT_LOOP_CONTROL_DESIGN   {0, 1, 1, 1, 0, KS_INIT_PHASEENCODING_PLAN_DESIGN, KS_INIT_PHASEENCODING_PLAN_DESIGN, KS_INIT_SLICETIMING_DESIGN}

Enumeration Type Documentation

◆ SMS_SLICE_ENCODING_DIRECTION

Enumerator
SMS_SLICE_ENCODING_DIRECTION_POS 
SMS_SLICE_ENCODING_DIRECTION_NEG 

Function Documentation

◆ ksscan_validate_slicetimingdesign()

STATUS ksscan_validate_slicetimingdesign ( const KS_SLICETIMING_DESIGN design)

Function that performs range checks for the fields in KS_SLICETIMING_DESIGN before it is used

Parameters
[in]designPointer to KS_SLICETIMING_DESIGN
Return values
STATUSSUCCESS or FAILURE
71  {
72 
73  if (design->nslices < 1 || design->nslices > 512) {
74  return KS_THROW("nslices (%d) must be in range [1,512]", design->nslices);
75  }
76  if (design->minacqs < 1 || design->minacqs > 512) {
77  return KS_THROW("minacqs (%d) must be in range [1,512]", design->minacqs);
78  }
79  if (design->inpass_interleaves < 1 || design->inpass_interleaves > 16) {
80  return KS_THROW("inpass_interleaves (%d) must be in range [1,16]", design->inpass_interleaves);
81  }
82 
83  if (design->minTR < 0) {
84  return KS_THROW("minTR (%d) must be >= 0", design->minTR);
85  }
86  if (design->maxTR < 0) {
87  return KS_THROW("maxTR (%d) must be >= 0", design->maxTR);
88  }
89  if (design->maxTR > 0 && (design->maxTR < design->minTR)) {
90  return KS_THROW("maxTR (%d) must be >= .minTR (%d)", design->maxTR, design->minTR);
91  }
92 
93  if (design->is3D) {
94  if (design->minacqs != 1) {
95  return KS_THROW("minacqs (%d) must be 1 in 3D mode", design->minacqs);
96  }
97  }
98 
99  if (design->nslices % design->sms_factor) {
100  return KS_THROW("#slices (%d) must be divisible with the SMS factor (%d)", design->nslices, design->sms_factor);
101  }
102 
103  return SUCCESS;
104 
105 } /* ksscan_validate_slicetimingdesign() */
int inpass_interleaves
Definition: ksscan.h:27
int minacqs
Definition: ksscan.h:26
int sms_factor
Definition: ksscan.h:25
int maxTR
Definition: ksscan.h:29
int nslices
Definition: ksscan.h:23
int is3D
Definition: ksscan.h:24
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
int minTR
Definition: ksscan.h:28

◆ ksscan_slicetiming_eval_design()

STATUS ksscan_slicetiming_eval_design ( KS_SLICETIMING slicetiming,
KS_SEQ_CONTROL sequence_to_inflate,
KS_CORESLICETIME   coresliceconst SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic,
const KS_SLICETIMING_DESIGN slicetiming_design 
)

Calculate the number of slices/TR and TR padding time (no use of CVs or global variables)

This function calculates the number of slices that can fit in one TR based on the duration and occurences of the sequence modules and the requested design. This function is intended to be a better alternative to GERequired.e:GEReq_eval_TR(), as it does not use any global variables and can therefore be called more than once with different parameters without interference. This is useful when a sequence contains more than one slice loop with different parameters, for instance a calibration step followed by the main loop.

Parameters
[out]slicetimingStruct containing all information for looping through the slices
[in,out]sequence_to_inflateThe sequence control for the module of choice to inflate (i.e. increase it .duration field) to meet the desired TR
[in]coresliceFunction pointer to a coreslice function playing one or more modules representing the kernel that is repeated within a TR for each slice location
[in]slicetiming_designDesign parameters for the calculation of
Return values
STATUSSUCCESS or FAILURE
188  {
189 
190  if (sequence_to_inflate->duration == 0) {
191  ksscan_init_slicetiming(slicetiming);
192  return SUCCESS;
193  }
194 
195  STATUS status;
196  int numacqs = 0;
197  int minacqs = KS_NOTSET;
198  int i;
199  int TR_for_thismanyslices = KS_NOTSET;
200  int TR_for_shortest_scantime = KS_NOTSET;
201  int nslices_perTR = KS_NOTSET;
202  int nslices_shortest_scantime = KS_NOTSET;
203  int shortest_scantime = KS_NOTSET;
204  int singleslice_time = KS_NOTSET;
205  int autoTR = KS_NOTSET;
206 
207  /* Copy fields */
208  slicetiming->is3D = slicetiming_design->is3D;
209 
210  /* Calculate the offset to the slice location for 3D scans */
211  slicetiming->slloc_offset = 0;
212  if (slicetiming_design->is3D &&
213  slicetiming_design->scan_info[1].optloc > slicetiming_design->scan_info[0].optloc) {
214  slicetiming->slloc_offset = slicetiming_design->nslices - 1;
215  }
216 
217  status = ksscan_eval_setup_rf_slices(slicetiming, slicetiming_design, !slicetiming_design->is3D);
218  KS_RAISE(status);
219 
220  /* N.B.: For the purpose of finding how many slices that can fit within one TR,
221  the terms 'per acqs', 'per pass', and 'per TR' are used synonymously here (and elsewhere) */
222 
223  if ((slicetiming_design->maxTR > 0) && (slicetiming_design->maxTR < slicetiming_design->minTR)) {
224  return KS_THROW(".maxTR (%.1f) must be >= .minTR (%.1f) , or KS_NOTSET (disabled)", slicetiming_design->maxTR / 100.0, slicetiming_design->minTR / 100.0);
225  }
226 
227  /* time for a single slice */
228  singleslice_time = _play_loop(1, coreslice);
229  if (singleslice_time <= 0) return KS_THROW("negative core slice duration (%d us)", singleslice_time);
230 
231  if ((slicetiming_design->maxTR > 0) && (slicetiming_design->maxTR < singleslice_time)) {
232  if (slicetiming_design->maxTR == slicetiming_design->minTR) {
233  return KS_THROW("TR (%.1f) must be > %.1f ms", slicetiming_design->maxTR / 1000.0, singleslice_time / 1000.0);
234  } else {
235  return KS_THROW("Max TR (%.1f) must be > %.1f ms", slicetiming_design->maxTR / 1000.0, singleslice_time / 1000.0);
236  }
237  }
238  if ((slicetiming_design->minTR > 0) && (slicetiming_design->minTR < singleslice_time)) {
239  return KS_THROW("Min TR (%.1f) must be > %.1f ms", slicetiming_design->minTR / 1000.0, singleslice_time / 1000.0);
240  }
241  if ((slicetiming_design->maxTR > 0) && (slicetiming_design->minTR > 0) &&
242  ((slicetiming_design->maxTR > slicetiming_design->minTR)) && ((slicetiming_design->maxTR - slicetiming_design->minTR) < singleslice_time)) {
243  return KS_THROW("The [design.minTR (%.1f), design.maxTR (%.1f)] interval must be > %.1f ms (or 0 for manual TR)", slicetiming_design->minTR / 1000.0, slicetiming_design->maxTR / 1000.0, singleslice_time / 1000.0);
244  }
245  if ((slicetiming_design->maxTR >= singleslice_time) && (slicetiming_design->maxTR == slicetiming_design->minTR)) {
246  autoTR = FALSE;
247  } else {
248  autoTR = TRUE;
249  }
250 
251  /* #acqs cannot exceed #slices. If sequential scanning, #acqs = #slices */
252  minacqs = slicetiming_design->minacqs;
253  if (minacqs < 1) {
254  minacqs = 1;
255  } else if (minacqs >= slicetiming->slice_plan.nslices) {
256  minacqs = slicetiming->slice_plan.nslices;
257  }
258 
259  int requested_maxslices_perTR = CEIL_DIV(slicetiming->slice_plan.nslices, minacqs);
260  int TR_for_requested_maxslices = _play_loop(requested_maxslices_perTR, coreslice);
261 
262  if (autoTR) {
263 
264  if (slicetiming_design->maxTR > 0) { /* in-range autoTR */
265 
266  /* Check which combination that results in the lowest scan time, and max/min # slices in range */
267  for (i = 1; i <= slicetiming->slice_plan.nslices; i++) {
268  numacqs = CEIL_DIV(slicetiming->slice_plan.nslices, i);
269  TR_for_thismanyslices = _play_loop(i, coreslice);
270  if ((TR_for_thismanyslices >= slicetiming_design->minTR) && (slicetiming_design->maxTR == 0 || TR_for_thismanyslices <= slicetiming_design->maxTR) && (numacqs >= minacqs)) {
271  /* if in TR range and numacqs >= minacqs */
272  if (shortest_scantime == KS_NOTSET) {
273  nslices_shortest_scantime = i;
274  shortest_scantime = TR_for_thismanyslices * numacqs;
275  TR_for_shortest_scantime = TR_for_thismanyslices;
276  } else if (TR_for_thismanyslices * numacqs <= shortest_scantime * 1.01) {
277  /* 1.01 to avoid round-off effects of TR_for_thismanyslices and to slightly favor fewer acqs and longer TRs
278  when the scantime is nearly identical */
279  nslices_shortest_scantime = i;
280  shortest_scantime = TR_for_thismanyslices * numacqs;
281  TR_for_shortest_scantime = TR_for_thismanyslices;
282  }
283  }
284  }
285 
286  if (shortest_scantime == KS_NOTSET && slicetiming_design->minTR > 0) {
287  /* failed to find solution within the interval, the range is probably too high for the set
288  of slices. Need to add padding to reach slicetiming_design->minTR */
289  if (TR_for_requested_maxslices < slicetiming_design->minTR) {
290  nslices_perTR = requested_maxslices_perTR;
291  slicetiming->TR = slicetiming_design->minTR;
292  } else {
293  return KS_THROW("Programming error");
294  }
295  } else {
296  nslices_perTR = nslices_shortest_scantime;
297  slicetiming->TR = TR_for_shortest_scantime;
298  }
299 
300  } else { /* minimum TR (using requested_minacqs) */
301 
302  nslices_perTR = requested_maxslices_perTR;
303  slicetiming->TR = IMax(2, TR_for_requested_maxslices, slicetiming_design->minTR);
304 
305  }
306 
307  /* .maxslices_per_TR corresponds to .design.maxTR so we know how many we COULD have fit in */
308  if (minacqs == slicetiming->slice_plan.nslices) {
309  slicetiming->maxslices_per_TR = 1; /* looks better for sequential */
310  } else if (slicetiming_design->maxTR == 0) {
311  slicetiming->maxslices_per_TR = 2048; /* GEs normal slice max value */
312  } else {
313  slicetiming->maxslices_per_TR = _maxslicespertr(slicetiming_design->maxTR, coreslice);
314  }
315 
316 
317 
318  } else { /* Manual TR (based on user input: slicetiming_design->minTR == slicetiming_design->maxTR, both > 0) */
319 
320  /* how many slices COULD we fit in this fixed TR (=.minTR=.maxTR) ? */
321  if (minacqs == slicetiming->slice_plan.nslices) { /* sequential */
322  nslices_perTR = 1;
323  slicetiming->maxslices_per_TR = 1;
324  } else {
325  slicetiming->maxslices_per_TR = _maxslicespertr(slicetiming_design->maxTR /* same here as .minTR */, coreslice);
326  /* requested_maxslices_perTR: max slices the user wants per TR in order to get at least 'minacqs' number of passes
327  slicetiming->maxslices_per_TR: how many slices that can fit in the fixed TR
328  Take the minimum of these two to get number of slices to actually play per TR
329  */
330  nslices_perTR = IMin(2, slicetiming->maxslices_per_TR, requested_maxslices_perTR);
331 
332  }
333  slicetiming->TR = slicetiming_design->minTR;
334 
335  } /* Auto/Manual TR */
336 
337  /* If SMS, check that nslices_perTR is an odd number (can some times be helped by adjusting #interleaves) */
338  int inpass_interleaves = slicetiming_design->inpass_interleaves;
339  status = ks_sms_check_divisibility(&inpass_interleaves, slicetiming_design->sms_factor, nslices_perTR, slicetiming->slice_plan.nslices);
340  KS_RAISE(status);
341 
342  /* setup the slice plan for the sequence */
343  ks_calc_sliceplan_interleaved(&slicetiming->slice_plan, slicetiming->slice_plan.nslices, nslices_perTR, inpass_interleaves);
344 
345  /* Update the number of instances of the sequence to be inflated given 'slicetiming->slice_plan.nslices_per_pass' number of slices
346  time [us] for one sequence playout incl. the SSI time and necessary dead time to
347  make up the expected TR. To be used in KS_SEQLENGTH() in pulsegen() */
348  sequence_to_inflate->nseqinstances = 0;
349  int timetoadd_perTR = slicetiming->TR - _play_loop(slicetiming->slice_plan.nslices_per_pass, coreslice);
350 
351  if (timetoadd_perTR < 0) {
352  return KS_THROW("Programming error");
353  }
354 
355  /* inflate the sequence to meet TR. If we have a non-standard sequence module to inflate during TR, which may not be executed
356  'slicetiming->slice_plan.nslices_per_pass' time for that many slices, we divide here instead with 'sequence_to_inflate->nseqinstances'
357  that just got the right value thanks to being reset to zero followed by _play_loop() a few lines above */
358  if (sequence_to_inflate->nseqinstances > 0) {
359  sequence_to_inflate->duration = RUP_GRD(sequence_to_inflate->duration + CEIL_DIV(timetoadd_perTR, sequence_to_inflate->nseqinstances));
360  } else {
361  return KS_THROW("the sequence to inflate (%s) not played in scan, cannot adjust duration for TR", sequence_to_inflate->description);
362  }
363 
364 
365  return SUCCESS;
366 
367 } /* ksscan_slicetiming_eval_design() */
int is3D
Definition: ksscan.h:45
void ksscan_init_slicetiming(KS_SLICETIMING *slicetiming)
Initialize a slice timing
Definition: ksscan.cc:17
int _maxslicespertr(int TR, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
Definition: ksscan.cc:164
int inpass_interleaves
Definition: ksscan.h:27
#define KS_NOTSET
Definition: KSFoundation.h:115
int minacqs
Definition: ksscan.h:26
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
int sms_factor
Definition: ksscan.h:25
int duration
Definition: KSFoundation.h:1227
int nseqinstances
Definition: KSFoundation.h:1225
int slloc_offset
Definition: ksscan.h:47
int nslices_per_pass
Definition: KSFoundation.h:1320
int TR
Definition: ksscan.h:43
STATUS ks_sms_check_divisibility(int *inpass_interleaves, const int sms_factor, const int nslices_per_pass, const int nslices)
Checks that nslices_per_pass is an odd number when accelerating with SMS
Definition: KSFoundation_host.c:6438
STATUS ksscan_eval_setup_rf_slices(KS_SLICETIMING *slicetiming, const KS_SLICETIMING_DESIGN *slicetiming_design, int is2D)
Setup the slice offsets that will be actually be used
Definition: ksscan.cc:381
#define KS_RAISE(status)
Definition: KSFoundation.h:190
int nslices
Definition: KSFoundation.h:1318
int maxTR
Definition: ksscan.h:29
s64 _play_loop(int nslices, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
Definition: ksscan.cc:152
int nslices
Definition: ksscan.h:23
SCAN_INFO scan_info[SLTAB_MAX]
Definition: ksscan.h:22
KS_DESCRIPTION description
Definition: KSFoundation.h:1234
int maxslices_per_TR
Definition: ksscan.h:44
KS_SLICE_PLAN slice_plan
Definition: ksscan.h:42
int is3D
Definition: ksscan.h:24
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
int minTR
Definition: ksscan.h:28

◆ ksscan_copy_slices()

void ksscan_copy_slices ( KS_SLICETIMING_DESIGN slicetiming_design,
const SCAN_INFO *  slice_pos 
)

Copying of the graphical slice prescription in the UI (scan_info[]) and opslquant to the KS_SLICETIMING_DESIGN structure

Parameters
[in,out]slicetiming_designPointer to KS_SLICETIMING. Fields design.nslices, design.scan_info and state.rf_scan_info set by this function from UI variables
[in]slice_posPosition of the slice to be played out (one element in the ks_scan_info[] array)
Returns
void
372  {
373 
374  memcpy(slicetiming_design->scan_info, scan_info, slicetiming_design->nslices * sizeof(SCAN_INFO));
375 
376 } /* ksscan_copy_slices() */
SCAN_INFO scan_info[]
int nslices
Definition: ksscan.h:23
SCAN_INFO scan_info[SLTAB_MAX]
Definition: ksscan.h:22

◆ ksscan_eval_setup_rf_slices()

STATUS ksscan_eval_setup_rf_slices ( KS_SLICETIMING slicetiming,
const KS_SLICETIMING_DESIGN slicetiming_design,
int  is2D 
)

Setup the slice offsets that will be actually be used

Internal use*

Parameters
[in,out]slicetimingPointer to KS_SLICETIMING
[in]slicetiming_designPointer to KS_SLICETIMING. Fields design.nslices, design.scan_info and state.rf_scan_info set by this function from UI variables
[in]is2DBoolean indicator for 2D
Return values
STATUSSUCCESS or FAILURE
382  {
383 
384  STATUS status = SUCCESS;
385 
386  if (slicetiming_design->nslices <= 0) {
387  return KS_THROW("slicetiming_design.nslices must be >= 1");
388  }
389 
390  slicetiming->sms_factor = slicetiming_design->sms_factor;
391 
392  if (is2D) {
393 
394  if (slicetiming_design->sms_factor > 1) { /* SMS */
395 
396  /* memcopy of design.scan_info into state.rf_scaninfo is done in ks_eval_sms_rf_scan_info */
397  slicetiming->slice_plan.nslices = ks_eval_sms_rf_scan_info(slicetiming->rf_scan_info,
398  slicetiming_design->scan_info,
399  slicetiming_design->sms_factor,
400  slicetiming_design->nslices);
401  if (slicetiming->slice_plan.nslices < 1) {
402  return KS_THROW("ks_eval_sms_rf_scan_info has failed");
403  }
404 
405  /* set sms_slice_encoding_direction */
406  slicetiming->sms_slice_encoding_direction = (0 < (slicetiming->rf_scan_info[1].optloc - slicetiming->rf_scan_info[0].optloc)) ? SMS_SLICE_ENCODING_DIRECTION_POS : SMS_SLICE_ENCODING_DIRECTION_NEG;
407 
408  } else { /* Normal 2D */
409 
410  slicetiming->slice_plan.nslices = slicetiming_design->nslices;
411  memcpy(slicetiming->rf_scan_info, slicetiming_design->scan_info, slicetiming->slice_plan.nslices * sizeof(SCAN_INFO));
412 
413  }
414 
415  } else { /* 3D mode */
416 
417  SCAN_INFO centerposition = slicetiming_design->scan_info[0];
418  /* SCAN_INFO centre_slices[opvquant]; used for multislab; TODO: figure out how multi-slab works*/
419  int centerslice = slicetiming_design->nslices/2;
420  slicetiming->slice_plan.nslices = 1;
421  /* for future 3D multislab support, let passindx update centerposition */
422  if (slicetiming_design->nslices == 1) {
423  centerposition.optloc = slicetiming_design->scan_info[0].optloc;
424  } else {
425  centerposition.optloc = (slicetiming_design->scan_info[centerslice-1].optloc +
426  slicetiming_design->scan_info[centerslice].optloc)/2.0;
427 
428  }
429  slicetiming->rf_scan_info[0] = centerposition;
430 
431  }
432 
433  return status;
434 
435 } /* ksscan_eval_setup_rf_slices() */
int sms_factor
Definition: ksscan.h:46
Definition: ksscan.h:16
SCAN_INFO rf_scan_info[KS_MAX_RF_SCANINFO]
Definition: ksscan.h:41
int ks_eval_sms_rf_scan_info(SCAN_INFO *sms_slice_positions, const SCAN_INFO *org_slice_positions, int sms_multiband_factor, int nslices)
Returns a new SCAN_INFO struct with a shifted slice postions
Definition: KSFoundation_host.c:3895
Definition: ksscan.h:16
int sms_factor
Definition: ksscan.h:25
SMS_SLICE_ENCODING_DIRECTION sms_slice_encoding_direction
Definition: ksscan.h:48
int nslices
Definition: KSFoundation.h:1318
int nslices
Definition: ksscan.h:23
SCAN_INFO scan_info[SLTAB_MAX]
Definition: ksscan.h:22
KS_SLICE_PLAN slice_plan
Definition: ksscan.h:42
#define KS_THROW(format,...)
Definition: KSFoundation.h:181

◆ ksscan_phaseencoding_plan_eval_design()

STATUS ksscan_phaseencoding_plan_eval_design ( KS_PHASEENCODING_PLAN pe_plan,
const KS_PHASEENCODING_PLAN_DESIGN design 
)

Generates a phase encodin plan according to design

This function is a wrapper for ks_generate_peplan_from_kcoords using a design struct instead of separated arguments.

Parameters
[out]pe_planPhase encoding plan to be generated
[in]designDesign of the phase encoding plan
Return values
STATUSSUCCESS or FAILURE
26  {
27  STATUS s;
28 
29  if (!design->kacq.coords) {
30  return KS_THROW("coords is NULL");
31  }
32 
33  strcpy(pe_plan->description, design->description);
34 
35  /* If repeated phase encoding plan is requested, change encodes_per_shot or center_encode */
36  int encodes_per_shot = design->encodes_per_shot;
37  int center_encode = design->center_encode;
38  if (design->repeat.num_repeats > 1) {
39  if (design->repeat.mode == INTERLEAVED_LONGER_SHOTS) { /* e.g. [1,3,2,4] -> [1, 1, 3, 3, 2, 2, 4, 4] */
40  encodes_per_shot /= design->repeat.num_repeats;
41  if (center_encode != KS_NOTSET) {
42  center_encode /= design->repeat.num_repeats;
43  }
44  }
45  /* TODO: Verify that other modes don't change encodes_per_shot and center_encode */
46  }
47 
49  pe_plan,
50  design->mtf_direction,
52  design->mtf_profile,
53  encodes_per_shot,
54  center_encode,
55  design->coord_type);
56  KS_RAISE(s);
57 
58  pe_plan->coord_type[0] = design->coord_type[0];
59  pe_plan->coord_type[1] = design->coord_type[1];
60 
61  s = ks_repeat_peplan(pe_plan, &design->repeat);
62  KS_RAISE(s);
63 
64  return SUCCESS;
65 
66 } /* ksscan_phaseencoding_plan_eval_design() */
int encodes_per_shot
Definition: ksscan.h:140
KS_MTF_DIRECTION mtf_direction
Definition: ksscan.h:142
KS_KSPACE_ACQ kacq
Definition: ksscan.h:138
#define KS_NOTSET
Definition: KSFoundation.h:115
KS_KCOORD * coords
Definition: KSFoundation.h:2228
KS_VIEW_SORT_ORDER encode_shot_assignment_order
Definition: ksscan.h:143
KS_VIEW_MTF_PROFILE mtf_profile
Definition: ksscan.h:144
KS_DESCRIPTION description
Definition: ksscan.h:137
KS_COORDINATE_TYPE coord_type[2]
Definition: KSFoundation.h:1793
KS_DESCRIPTION description
Definition: KSFoundation.h:1791
KS_PHASEENCODING_REPEAT_DESIGN repeat
Definition: ksscan.h:145
KS_REPEAT_MODE mode
Definition: KSFoundation.h:2258
#define KS_RAISE(status)
Definition: KSFoundation.h:190
STATUS ks_generate_peplan_from_kcoords(const KS_KSPACE_ACQ *kacq, KS_PHASEENCODING_PLAN *peplan, KS_MTF_DIRECTION mtf_direction, KS_VIEW_SORT_ORDER encode_shot_assignment_order, KS_VIEW_MTF_PROFILE mtf_profile, const int etl, int center, const KS_COORDINATE_TYPE *const coord_types) WARN_UNUSED_RESULT
Phase encoding plan generators
Definition: KSFoundation_host.c:9511
int center_encode
Definition: ksscan.h:141
Definition: KSFoundation.h:2244
STATUS ks_repeat_peplan(KS_PHASEENCODING_PLAN *peplan, const KS_PHASEENCODING_REPEAT_DESIGN *const repeat)
ADDTITLEHERE
Definition: KSFoundation_host.c:8143
#define KS_THROW(format,...)
Definition: KSFoundation.h:181
int num_repeats
Definition: KSFoundation.h:2259
KS_COORDINATE_TYPE coord_type[2]
Definition: ksscan.h:139

◆ ksscan_loop_control_eval_design()

STATUS ksscan_loop_control_eval_design ( KSSCAN_LOOP_CONTROL loop_control,
KS_SEQ_CONTROL sequence_to_inflate,
KS_CORESLICETIME   coresliceconst SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic,
const KSSCAN_LOOP_CONTROL_DESIGN design 
)

Generates a loop control

This function should be the default way to generating a loop control.

Parameters
[out]loop_controlLoop control to be generated. It contains all information needed for a standard scan loop
[in,out]sequence_to_inflateControl for the sequence that is to be inflated if needed to adjust the TR timing
[in]coresliceFunction pointer to a coreslice function playing one or more modules representing the kernel that is repeated within a TR for each slice location
[in]designDesign of the loop control
Return values
STATUSSUCCESS or FAILURE
113  {
114 
115  STATUS s;
116 
117  if (sequence_to_inflate->duration == 0) {
118  ksscan_init_loopcontrol(loop_control);
119  return SUCCESS;
120  }
121 
122  /* copy fields */
123  loop_control->dda = design->dda;
124  loop_control->nvols = design->nvols;
125  loop_control->naverages = design->naverages;
126  loop_control->play_endofpass = design->play_endofpass;
127  loop_control->interleaved_snapshot = design->interleaved_snapshot;
128 
130  KS_RAISE(s);
131 
132  /* Only eval the dummy plan if there are coords */
133  if (design->phaseenc_design_dummies.kacq.coords) {
135  KS_RAISE(s);
136  }
137 
138  s = ksscan_slicetiming_eval_design(&loop_control->slicetiming,
139  sequence_to_inflate,
140  coreslice,
141  &design->slicetiming_design);
142  KS_RAISE(s);
143 
144  return SUCCESS;
145 
146 } /* ksscan_loop_control_eval_design() */
STATUS ksscan_phaseencoding_plan_eval_design(KS_PHASEENCODING_PLAN *pe_plan, const KS_PHASEENCODING_PLAN_DESIGN *design)
Generates a phase encodin plan according to design
Definition: ksscan.cc:26
int interleaved_snapshot
Definition: ksscan.h:189
KS_PHASEENCODING_PLAN_DESIGN phaseenc_design_dummies
Definition: ksscan.h:208
KS_KSPACE_ACQ kacq
Definition: ksscan.h:138
KS_PHASEENCODING_PLAN phaseenc_plan_dummies
Definition: ksscan.h:191
KS_SLICETIMING slicetiming
Definition: ksscan.h:192
KS_KCOORD * coords
Definition: KSFoundation.h:2228
int naverages
Definition: ksscan.h:204
int play_endofpass
Definition: ksscan.h:188
KS_PHASEENCODING_PLAN_DESIGN phaseenc_design
Definition: ksscan.h:207
int duration
Definition: KSFoundation.h:1227
int dda
Definition: ksscan.h:185
int naverages
Definition: ksscan.h:187
int dda
Definition: ksscan.h:202
int nvols
Definition: ksscan.h:203
KS_SLICETIMING_DESIGN slicetiming_design
Definition: ksscan.h:209
int play_endofpass
Definition: ksscan.h:205
#define KS_RAISE(status)
Definition: KSFoundation.h:190
void ksscan_init_loopcontrol(KSSCAN_LOOP_CONTROL *loop_control)
Initialize a loop control
Definition: ksscan.cc:8
STATUS ksscan_slicetiming_eval_design(KS_SLICETIMING *slicetiming, KS_SEQ_CONTROL *sequence_to_inflate, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic), const KS_SLICETIMING_DESIGN *slicetiming_design)
Calculate the number of slices/TR and TR padding time (no use of CVs or global variables)
Definition: ksscan.cc:185
KS_PHASEENCODING_PLAN phaseenc_plan
Definition: ksscan.h:190
int interleaved_snapshot
Definition: ksscan.h:206
int nvols
Definition: ksscan.h:186

◆ ksscan_sliceloop()

s64 ksscan_sliceloop ( const KSSCAN_LOOP_CONTROL loop_control,
KS_DYNAMIC_STATE *  dynamic,
KS_CORESLICETIME   coresliceconst SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic 
)

Executes all loops for a single TR

Usually it loops only over slices but, if the flag interleaved_snapshot is set, it loops over shots for each slice position.

Parameters
[in]loop_controlLoop control containing all information needed for a standard scan loop
[in,out]dynamicPointer to KS_DYNAMIC_STATE used to loop and ultimately set the state of the module(s) played
[in]coresliceFunction pointer to a coreslice function playing one or more modules representing the kernel that is repeated within a TR for each slice location
Return values
s64Duration of a single TR
460  {
461  s64 time = 0;
462  const SCAN_INFO *current_slice = NULL;
463  const int num_shots = loop_control->interleaved_snapshot ? loop_control->phaseenc_plan.num_shots : 1;
464 
465  for (dynamic->sltimeinpass = 0; dynamic->sltimeinpass < loop_control->slicetiming.slice_plan.nslices_per_pass; dynamic->sltimeinpass++) {
466  for (dynamic->inner_shot = 0; dynamic->inner_shot < num_shots; dynamic->inner_shot++) {
467 
468  if (loop_control->interleaved_snapshot && dynamic->shot >= 0) {
469  /*
470  When running in interleaved snapshot mode, we need to use the inner shot index to retrieve the shot coordinates.
471  Note that, we should not overwrite the shot coordinates for dummies so that the phasers will be turned off as
472  expected. Hence, if shot index is negative shot_coords is not updated.
473  */
474  dynamic->shot_coords = ks_phaseencoding_get_shot(&loop_control->phaseenc_plan, dynamic->inner_shot);
475  }
476 
477  if (loop_control->slicetiming.is3D) { /* 3D */
478  dynamic->slloc = 0;
479  /* Store the offset so that coreslice can get information about the slice stack's direction */
480  dynamic->slloc_offset = loop_control->slicetiming.slloc_offset;
481  } else { /* 2D */
482  /* slice location from slice plan */
483  dynamic->slloc = ks_scan_getsliceloc(&loop_control->slicetiming.slice_plan, dynamic->pass, dynamic->sltimeinpass);
484  }
485 
486  /* if dynamic->slloc = KS_NOTSET, pass in NULL as first argument to indicate 'false slice' */
487  current_slice = (dynamic->slloc != KS_NOTSET) ?
488  &loop_control->slicetiming.rf_scan_info[dynamic->slloc] : NULL;
489 
490  if (coreslice) {
491  time += coreslice(current_slice, dynamic).duration;
492  }
493 
494  } /* inner shot */
495  } /* slice loop */
496 
497  return time; /* in [us] */
498 
499 } /* ksscan_sliceloop() */
int is3D
Definition: ksscan.h:45
SCAN_INFO rf_scan_info[KS_MAX_RF_SCANINFO]
Definition: ksscan.h:41
int interleaved_snapshot
Definition: ksscan.h:189
int num_shots
Definition: KSFoundation.h:1789
#define KS_NOTSET
Definition: KSFoundation.h:115
KS_SLICETIMING slicetiming
Definition: ksscan.h:192
int duration
Definition: ksscan.h:73
int slloc_offset
Definition: ksscan.h:47
int nslices_per_pass
Definition: KSFoundation.h:1320
KS_PHASEENCODING_PLAN phaseenc_plan
Definition: ksscan.h:190
KS_PHASEENCODING_SHOTCOORDS ks_phaseencoding_get_shot(const KS_PHASEENCODING_PLAN *phaseenc_plan_ptr, int shot)
ADDTITLEHERE
Definition: KSFoundation_common.c:623
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
KS_SLICE_PLAN slice_plan
Definition: ksscan.h:42

◆ ksscan_acqloop()

s64 ksscan_acqloop ( const KSSCAN_LOOP_CONTROL loop_control,
KS_DYNAMIC_STATE *  dynamic,
KS_CORESLICETIME   coresliceconst SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic 
)

Executes all loops for a single pass/acquisition

Parameters
[in]loop_controlLoop control containing all information needed for a standard scan loop
[in,out]dynamicPointer to KS_DYNAMIC_STATE used to loop and ultimately set the state of the module(s) played
[in]coresliceFunction pointer that plays one or several modules representing the kernel that is repeated within a TR for each slice location
Return values
s64Duration of a single pass/acquisition
506  {
507  s64 time = 0;
508  char slicegroup_desc[256];
509 
510  /* shot < 0 means dummy scans */
511  const int num_shots = loop_control->interleaved_snapshot ? 1 : loop_control->phaseenc_plan.num_shots;
512  for (dynamic->shot = -loop_control->dda; dynamic->shot < num_shots; dynamic->shot++) {
513 
514  const int naverages = dynamic->shot < 0 ? 1 : loop_control->naverages;
515  dynamic->shot_coords = dynamic->shot >= 0 ? ks_phaseencoding_get_shot(&loop_control->phaseenc_plan, dynamic->shot)
516  : ks_phaseencoding_get_shot(&loop_control->phaseenc_plan_dummies, -dynamic->shot - 1);
517 
518  for (dynamic->average = 0; dynamic->average < naverages; dynamic->average++) {
519 
520  time += ksscan_sliceloop(loop_control, dynamic, coreslice);
521 
522  sprintf(slicegroup_desc, "%s - pass %d shot %d average %d",
523  "Generic loop", /*seq->design.description,*/
524  dynamic->pass, dynamic->shot, dynamic->average);
525  ks_plot_slicetime_endofslicegroup_tagged(slicegroup_desc, (dynamic->shot < 0) ? KS_PLOT_SG_DUMMY : KS_PLOT_SG_ACQUISITION);
526  } /* for average */
527 
528  } /* for shot */
529 
530  return time; /* in [us] */
531 
532 } /* ksscan_acqloop() */
int interleaved_snapshot
Definition: ksscan.h:189
int num_shots
Definition: KSFoundation.h:1789
int dda
Definition: ksscan.h:185
int naverages
Definition: ksscan.h:187
s64 ksscan_sliceloop(const KSSCAN_LOOP_CONTROL *loop_control, KS_DYNAMIC_STATE *dynamic, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
Executes all loops for a single TR
Definition: ksscan.cc:458
void ks_plot_slicetime_endofslicegroup_tagged(const char *desc, const KS_PLOT_SLICEGROUP_MODE tag)
ADDTITLEHERE
Definition: KSFoundation_common.c:4296
KS_PHASEENCODING_PLAN phaseenc_plan
Definition: ksscan.h:190
Definition: KSFoundation.h:412
Definition: KSFoundation.h:414
KS_PHASEENCODING_SHOTCOORDS ks_phaseencoding_get_shot(const KS_PHASEENCODING_PLAN *phaseenc_plan_ptr, int shot)
ADDTITLEHERE
Definition: KSFoundation_common.c:623

◆ ksscan_plotloop_shots()

void ksscan_plotloop_shots ( const KSSCAN_LOOP_CONTROL loop_control,
KS_CORESLICETIME   coresliceconst SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic 
)

Executes a single-slice single-pass scan loop used for plotting all shots states

Parameters
[in]loop_controlLoop control containing all information needed for a standard scan loop
[in]coresliceFunction pointer that plays one or more modules representing the kernel that is repeated within a TR for each slice location
Returns
void
538  {
539  KSSCAN_LOOP_CONTROL plot_control = *loop_control;
540  plot_control.nvols = 1;
541  plot_control.naverages = 1;
542  plot_control.slicetiming.slice_plan.npasses = 1;
543  plot_control.slicetiming.slice_plan.nslices_per_pass = 1;
544  ksscan_scanloop(&plot_control, NULL, coreslice);
545 
546 } /* ksscan_plotloop_shots() */
KS_SLICETIMING slicetiming
Definition: ksscan.h:192
int nslices_per_pass
Definition: KSFoundation.h:1320
int naverages
Definition: ksscan.h:187
int npasses
Definition: KSFoundation.h:1319
Structure containing all the information to perform a standard scan loop
Definition: ksscan.h:184
s64 ksscan_scanloop(const KSSCAN_LOOP_CONTROL *orig_loop_control, KS_DYNAMIC_STATE *dynamic, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
Executes all loops according to the provided loop control
Definition: ksscan.cc:564
int nvols
Definition: ksscan.h:186
KS_SLICE_PLAN slice_plan
Definition: ksscan.h:42

◆ ksscan_plotloop_slices()

void ksscan_plotloop_slices ( const KSSCAN_LOOP_CONTROL loop_control,
KS_CORESLICETIME   coresliceconst SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic 
)

Executes a single-shot single-pass scan loop used for plotting all slices states

Parameters
[in]loop_controlLoop control containing all information needed for a standard scan loop
[in]coresliceFunction pointer to a coreslice function playing one or more modules representing the kernel that is repeated within a TR for each slice location
Returns
void
552  {
553  KSSCAN_LOOP_CONTROL plot_control = *loop_control;
554  plot_control.nvols = 1;
555  plot_control.naverages = 1;
556  plot_control.phaseenc_plan.num_shots = 1;
557  ksscan_scanloop(&plot_control, NULL, coreslice);
558 
559 } /* ksscan_plotloop_slices() */
int num_shots
Definition: KSFoundation.h:1789
int naverages
Definition: ksscan.h:187
Structure containing all the information to perform a standard scan loop
Definition: ksscan.h:184
s64 ksscan_scanloop(const KSSCAN_LOOP_CONTROL *orig_loop_control, KS_DYNAMIC_STATE *dynamic, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
Executes all loops according to the provided loop control
Definition: ksscan.cc:564
KS_PHASEENCODING_PLAN phaseenc_plan
Definition: ksscan.h:190
int nvols
Definition: ksscan.h:186

◆ ksscan_scanloop()

s64 ksscan_scanloop ( const KSSCAN_LOOP_CONTROL orig_loop_control,
KS_DYNAMIC_STATE *  dynamic,
KS_CORESLICETIME   coresliceconst SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic 
)

Executes all loops according to the provided loop control

Parameters
[in]orig_loop_controlLoop control containing all information needed for a standard scan loop
[in,out]dynamicPointer to KS_DYNAMIC_STATE used to loop and ultimately set the state of the module(s) played
[in]coresliceFunction pointer to a coreslice function playing one or more modules representing the kernel that is repeated within a TR for each slice location
Return values
s64Duration of the whole scan
566  {
567  s64 time = 0;
568  KSSCAN_LOOP_CONTROL loop_control = *orig_loop_control;
569  KS_DYNAMIC_STATE default_dynamic = KS_INIT_DYNAMIC_STATE;
570  if (!dynamic) {
571  dynamic = &default_dynamic;
572  }
573 
574  for (dynamic->vol = 0; dynamic->vol < loop_control.nvols; dynamic->vol++) {
575  for (dynamic->pass = 0; dynamic->pass < loop_control.slicetiming.slice_plan.npasses; dynamic->pass++) {
576 
577  /* In a single pass scan we should play dummies only once */
578  loop_control.dda = loop_control.slicetiming.slice_plan.npasses == 1 ?
579  (!dynamic->vol)*orig_loop_control->dda :
580  orig_loop_control->dda;
581 
582  time += ksscan_acqloop(&loop_control, dynamic, coreslice);
583 
584  loop_control.dda = 0;
585  if (loop_control.play_endofpass) {
586  time += GEReq_endofpass();
587  }
589  } /* pass loop */
590  } /* volume loop */
591 
592  return time; /* in [us] */
593 
594 } /* ksscan_scanloop() */
int GEReq_endofpass()
Sets SSP word in sequence off_GEpass() to trigger data (Pfile) writing and reconstruction
Definition: GERequired.e:3621
KS_SLICETIMING slicetiming
Definition: ksscan.h:192
int play_endofpass
Definition: ksscan.h:188
s64 ksscan_acqloop(const KSSCAN_LOOP_CONTROL *loop_control, KS_DYNAMIC_STATE *dynamic, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
Executes all loops for a single pass/acquisition
Definition: ksscan.cc:504
int dda
Definition: ksscan.h:185
int npasses
Definition: KSFoundation.h:1319
#define KS_INIT_DYNAMIC_STATE
Definition: KSFoundation.h:1829
Structure containing all the information to perform a standard scan loop
Definition: ksscan.h:184
void ks_plot_slicetime_endofpass(KS_PLOT_PASS_MODE pass_mode)
ADDTITLEHERE
Definition: KSFoundation_common.c:4286
Definition: KSFoundation.h:409
int nvols
Definition: ksscan.h:186
KS_SLICE_PLAN slice_plan
Definition: ksscan.h:42

◆ ksscan_prescanloop()

void ksscan_prescanloop ( const KSSCAN_LOOP_CONTROL loop_control,
KS_CORESLICETIME   coresliceconst SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic,
int  nloops,
int  dda 
)

Executes a prescan loop

It consist of of a number of dummies TRs equal to dda where dynamic.shot = KS_NOTSET followed by nloops TRs where dynamic.shot = 0 and dynamic.shot_coords = {0, NULL} to indicate to the coreslice to turn off all phase encoding. The flag dynamic.prescan is set so that the coreslice can turn off the data routing for all but the readout with the highest expected signal.

Parameters
[in]loop_controlLoop control containing all information needed for a standard scan loop
[in]coresliceFunction pointer to a coreslice function playing one or more modules representing the kernel that is repeated within a TR for each slice location
[in]nloopsNumber of repetitions to be scanned
[in]ddaNumber of dummy repetitions to be played before turning the data acquisition on
Return values
void

Executes a prescan loop

605  {
606 
608  KS_DYNAMIC_STATE dynamic = KS_INIT_DYNAMIC_STATE;
609  dynamic.prescan = 1;
610  dynamic.shot_coords = fake_shot;
611 
612  int i;
613  for (i = -dda; i < nloops; i++) {
614  /* negative shot always closes data receiver during prescan */
615  dynamic.shot = (dda < 0) * KS_NOTSET;
616  ksscan_sliceloop(loop_control, &dynamic, coreslice);
617  } /* for nloops */
618 
619 } /* ksscan_prescanloop() */
ADDTITLEHERE
Definition: KSFoundation.h:1773
#define KS_NOTSET
Definition: KSFoundation.h:115
#define KS_INIT_DYNAMIC_STATE
Definition: KSFoundation.h:1829
#define KS_INIT_PHASEENCODING_SHOTCOORDS
Definition: KSFoundation.h:1778
s64 ksscan_sliceloop(const KSSCAN_LOOP_CONTROL *loop_control, KS_DYNAMIC_STATE *dynamic, KS_CORESLICETIME coreslice(const SCAN_INFO *slice_pos, KS_DYNAMIC_STATE *dynamic))
Executes all loops for a single TR
Definition: ksscan.cc:458

◆ ksscan_init_loopcontrol()

void ksscan_init_loopcontrol ( KSSCAN_LOOP_CONTROL loop_control)

Initialize a loop control

Parameters
[out]loop_controlLoop control to be initialized
Returns
void
8  {
10  *loop_control = loop_init;
11 
12 } /* ksscan_init_loopcontrol() */
Structure containing all the information to perform a standard scan loop
Definition: ksscan.h:184
#define KSSCAN_INIT_LOOP_CONTROL
Definition: ksscan.h:195

◆ ksscan_init_slicetiming()

void ksscan_init_slicetiming ( KS_SLICETIMING slicetiming)

Initialize a slice timing

Parameters
[out]slicetimingSlice timing to be initialized
Returns
void
17  {
18  KS_SLICETIMING slicetiming_init = KS_INIT_SLICETIMING;
19  *slicetiming = slicetiming_init;
20 
21 } /* ksscan_init_slicetiming() */
Struct holding the &#39;consequence&#39; variables such as slice plan and TR. These fields should not be set ...
Definition: ksscan.h:40
#define KS_INIT_SLICETIMING
Definition: ksscan.h:51

◆ ks_plot_psd()

void ks_plot_psd ( const KS_SEQ_CONTROL ctrl,
const KSSCAN_LOOP_CONTROL loopctrl 
)

Wrapper function for plotting a module/sequence entry

It handles the cases where negative shots are also used for encoding

Parameters
ctrlControl of the module to be plotted
loopctrlLoop control, can be NULL.
Returns
void
440  {
441  if (loopctrl) {
442  const KS_PHASEENCODING_PLAN* plans[2] = {&loopctrl->phaseenc_plan, &loopctrl->phaseenc_plan_dummies};
443  ks_plot_host_seqctrl_manyplans(ctrl, plans, loopctrl->phaseenc_plan_dummies.num_shots > 0 ? 2 : 1);
444  } else {
445  ks_plot_host_seqctrl(ctrl, NULL);
446  }
447 
448 } /* ks_plot_psd() */
int num_shots
Definition: KSFoundation.h:1789
ADDTITLEHERE
Definition: KSFoundation.h:1787
void ks_plot_host_seqctrl_manyplans(const KS_SEQ_CONTROL *ctrl, const KS_PHASEENCODING_PLAN **plan, const int num_plans)
ADDTITLEHERE
Definition: KSFoundation_host.c:7721
KS_PHASEENCODING_PLAN phaseenc_plan_dummies
Definition: ksscan.h:191
void ks_plot_host_seqctrl(const KS_SEQ_CONTROL *ctrl, const KS_PHASEENCODING_PLAN *plan)
ADDTITLEHERE
Definition: KSFoundation_host.c:7596
KS_PHASEENCODING_PLAN phaseenc_plan
Definition: ksscan.h:190