# algorithms.slicetiming.timefuncs

## Module: `algorithms.slicetiming.timefuncs`

Utility functions for returning slice times from number of slices and TR

Slice timing routines in nipy need a vector of slice times.

Slice times are vectors \(t_i\) with \(i = 0 ... N\) of times, one for each slice, where \(t_i\) gives the time at which slice number \(i\) was acquired, relative to the beginning of the volume acquisition.

We like these vectors because they are unambiguous; the indices \(i\) refer to positions in space, and the values \(t_i\) refer to times.

But, there are many common slice timing regimes for which it’s easy to get the slice times once you know the volume acquisition time (the TR) and the number of slices.

For example, if you acquired the slices in a simple ascending order, and you have 10 slices and the TR was 2.0, then the slice times are:

    >>> import numpy as np
    >>> np.arange(10) / 10.  * 2.0
    array([ 0. ,  0.2,  0.4,  0.6,  0.8,  1. ,  1.2,  1.4,  1.6,  1.8])

These are small convenience functions that accept the number of slices and the TR as input, and return a vector of slice times:

    >>> ascending(10, 2.)
    array([ 0. ,  0.2,  0.4,  0.6,  0.8,  1. ,  1.2,  1.4,  1.6,  1.8])

## Functions

nipy.algorithms.slicetiming.timefuncs.st_01234(n_slices, TR)

  Simple ascending slice sequence

  slice 0 first, slice 1 second etc.

  For example, for 5 slices and a TR of 1:

      >>> st_01234(5, 1.)
      array([ 0. ,  0.2,  0.4,  0.6,  0.8])

  Note: slice 0 is the first slice in the voxel data block

  Parameters:
    n_slices int

      Number of slices in volume

    TR float

      Time to acquire one full volume

  Returns:
    slice_times(n_slices,) ndarray

      Vectors \(t_i i = 0 ... N\) of times, one for each slice, where \(t_i\) gives the time at which slice number \(i\) was acquired, relative to the beginning of the volume acquisition.

nipy.algorithms.slicetiming.timefuncs.st_02413(n_slices, TR)

  Ascend alternate every second slice, starting at first slice

  Collect slice 0 first, slice 2 second up to top. Then return to collect slice 1, slice 3 etc.

  For example, for 5 slices and a TR of 1:

      >>> st_02413(5, 1.)
      array([ 0. ,  0.6,  0.2,  0.8,  0.4])

  Note: slice 0 is the first slice in the voxel data block

  Parameters:
    n_slices int

      Number of slices in volume

    TR float

      Time to acquire one full volume

  Returns:
    slice_times(n_slices,) ndarray

      Vectors \(t_i i = 0 ... N\) of times, one for each slice, where \(t_i\) gives the time at which slice number \(i\) was acquired, relative to the beginning of the volume acquisition.

nipy.algorithms.slicetiming.timefuncs.st_03142(n_slices, TR)

  Ascend alternate, where alternation is by half the volume

  Collect slice 0 then slice `ceil(n_slices / 2.)` then slice 1 then slice `ceil(nslices / 2.) + 1` etc.

  For example, for 5 slices and a TR of 1:

      >>> st_03142(5, 1.)
      array([ 0. ,  0.4,  0.8,  0.2,  0.6])

  Note: slice 0 is the first slice in the voxel data block

  Parameters:
    n_slices int

      Number of slices in volume

    TR float

      Time to acquire one full volume

  Returns:
    slice_times(n_slices,) ndarray

      Vectors \(t_i i = 0 ... N\) of times, one for each slice, where \(t_i\) gives the time at which slice number \(i\) was acquired, relative to the beginning of the volume acquisition.

nipy.algorithms.slicetiming.timefuncs.st_13024(n_slices, TR)

  Ascend alternate every second slice, starting at second slice

  Collect slice 1 first, slice 3 second up to top (highest numbered slice). Then return to collect slice 0, slice 2 etc. This order is rare except on Siemens acquisitions with an even number of slices. See `st_odd0_even1()` for this logic.

  For example, for 5 slices and a TR of 1:

      >>> st_13024(5, 1.)
      array([ 0.4,  0. ,  0.6,  0.2,  0.8])

  Note: slice 0 is the first slice in the voxel data block

  Parameters:
    n_slices int

      Number of slices in volume

    TR float

      Time to acquire one full volume

  Returns:
    slice_times(n_slices,) ndarray

      Vectors \(t_i i = 0 ... N\) of times, one for each slice, where \(t_i\) gives the time at which slice number \(i\) was acquired, relative to the beginning of the volume acquisition.

nipy.algorithms.slicetiming.timefuncs.st_41302(n_slices, TR)

  Descend alternate, where alternation is by half the volume

  Collect slice `(n_slices - 1)` then slice `floor(nslices / 2.) - 1` then slice `(n_slices - 2)` then slice `floor(nslices / 2.) - 2` etc.

  For example, for 5 slices and a TR of 1:

      >>> st_41302(5, 1.)
      array([ 0.6,  0.2,  0.8,  0.4,  0. ])

  Note: slice 0 is the first slice in the voxel data block

  Parameters:
    n_slices int

      Number of slices in volume

    TR float

      Time to acquire one full volume

  Returns:
    slice_times(n_slices,) ndarray

      Vectors \(t_i i = 0 ... N\) of times, one for each slice, where \(t_i\) gives the time at which slice number \(i\) was acquired, relative to the beginning of the volume acquisition.

nipy.algorithms.slicetiming.timefuncs.st_42031(n_slices, TR)

  Descend alternate every second slice, starting at last slice

  Collect slice (n_slices - 1) first, slice (nslices - 3) second down to bottom (lowest numbered slice). Then return to collect slice (n_slices -2), slice (n_slices - 4) etc.

  For example, for 5 slices and a TR of 1:

      >>> st_42031(5, 1.)
      array([ 0.4,  0.8,  0.2,  0.6,  0. ])

  Note: slice 0 is the first slice in the voxel data block

  Parameters:
    n_slices int

      Number of slices in volume

    TR float

      Time to acquire one full volume

  Returns:
    slice_times(n_slices,) ndarray

      Vectors \(t_i i = 0 ... N\) of times, one for each slice, where \(t_i\) gives the time at which slice number \(i\) was acquired, relative to the beginning of the volume acquisition.

nipy.algorithms.slicetiming.timefuncs.st_43210(n_slices, TR)

  Simple descending slice sequence

  slice `n_slices-1` first, slice `n_slices - 2` second etc.

  For example, for 5 slices and a TR of 1:

      >>> st_43210(5, 1.)
      array([ 0.8,  0.6,  0.4,  0.2,  0. ])

  Note: slice 0 is the first slice in the voxel data block

  Parameters:
    n_slices int

      Number of slices in volume

    TR float

      Time to acquire one full volume

  Returns:
    slice_times(n_slices,) ndarray

      Vectors \(t_i i = 0 ... N\) of times, one for each slice, where \(t_i\) gives the time at which slice number \(i\) was acquired, relative to the beginning of the volume acquisition.

nipy.algorithms.slicetiming.timefuncs.st_odd0_even1(n_slices, TR)

  Ascend alternate starting at slice 0 for odd, slice 1 for even n_slices

  Acquisitions with alternating ascending slices from Siemens scanners often seem to have this behavior as default - see:

  > https://mri.radiology.uiowa.edu/fmri_images.html

  This means we use the `st_02413()` algorithm if n_slices is odd, and the `st_13024()` algorithm if n_slices is even.

  For example, for 4 slices and a TR of 1:

      >>> st_odd0_even1(4, 1.)
      array([ 0.5 ,  0.  ,  0.75,  0.25])

  5 slices and a TR of 1:

      >>> st_odd0_even1(5, 1.)
      array([ 0. ,  0.6,  0.2,  0.8,  0.4])

  Note: slice 0 is the first slice in the voxel data block

  Parameters:
    n_slices int

      Number of slices in volume

    TR float

      Time to acquire one full volume

  Returns:
    slice_times(n_slices,) ndarray

      Vectors \(t_i i = 0 ... N\) of times, one for each slice, where \(t_i\) gives the time at which slice number \(i\) was acquired, relative to the beginning of the volume acquisition.