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.
190 if (sequence_to_inflate->
duration == 0) {
200 int TR_for_shortest_scantime =
KS_NOTSET;
202 int nslices_shortest_scantime =
KS_NOTSET;
208 slicetiming->
is3D = slicetiming_design->
is3D;
212 if (slicetiming_design->
is3D &&
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);
229 if (singleslice_time <= 0)
return KS_THROW(
"negative core slice duration (%d us)", singleslice_time);
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);
235 return KS_THROW(
"Max TR (%.1f) must be > %.1f ms", slicetiming_design->
maxTR / 1000.0, singleslice_time / 1000.0);
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);
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);
245 if ((slicetiming_design->
maxTR >= singleslice_time) && (slicetiming_design->
maxTR == slicetiming_design->
minTR)) {
252 minacqs = slicetiming_design->
minacqs;
259 int requested_maxslices_perTR = CEIL_DIV(slicetiming->
slice_plan.
nslices, minacqs);
260 int TR_for_requested_maxslices =
_play_loop(requested_maxslices_perTR, coreslice);
264 if (slicetiming_design->
maxTR > 0) {
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)) {
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) {
279 nslices_shortest_scantime = i;
280 shortest_scantime = TR_for_thismanyslices * numacqs;
281 TR_for_shortest_scantime = TR_for_thismanyslices;
286 if (shortest_scantime ==
KS_NOTSET && slicetiming_design->
minTR > 0) {
289 if (TR_for_requested_maxslices < slicetiming_design->minTR) {
290 nslices_perTR = requested_maxslices_perTR;
291 slicetiming->
TR = slicetiming_design->
minTR;
293 return KS_THROW(
"Programming error");
296 nslices_perTR = nslices_shortest_scantime;
297 slicetiming->
TR = TR_for_shortest_scantime;
302 nslices_perTR = requested_maxslices_perTR;
303 slicetiming->
TR = IMax(2, TR_for_requested_maxslices, slicetiming_design->
minTR);
310 }
else if (slicetiming_design->
maxTR == 0) {
330 nslices_perTR = IMin(2, slicetiming->
maxslices_per_TR, requested_maxslices_perTR);
333 slicetiming->
TR = slicetiming_design->
minTR;
351 if (timetoadd_perTR < 0) {
352 return KS_THROW(
"Programming error");
361 return KS_THROW(
"the sequence to inflate (%s) not played in scan, cannot adjust duration for TR", sequence_to_inflate->
description);
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