calc_projection_shell

calc_projection_shell#

pypulseqpp.calc_projection_shell()[source]#

Return a pole-to-pole base shell and z-axis rotations for each shot.

Consecutive base directions have equal angular separation. Rotated shells share both poles; each nonpolar ring has one spoke per shot.

Parameters:
  • n_views (int) – Spokes in the base shell, at least three.

  • n_shots (int, default=1) – Rotated replays of that shell.

  • scheme ({'spiral', 'meridian'}, default='spiral') – 'spiral' winds pole to pole across equal-area rings, so the shell alone is already near-uniform. 'meridian' is a half great circle in the x-z plane at equal polar steps, which is simpler and oversamples the poles.

Returns:

  • directions (numpy.ndarray) – Unit spoke directions of the base shell, shape (n_views, 3).

  • rotations (numpy.ndarray) – Rotation matrices, shape (n_shots, 3, 3), each turning the whole shell to where that shot samples.

Raises:

ValueError – If a count is out of range or scheme is unknown.

Examples

>>> import numpy as np
>>> import pypulseqpp as pp
>>> directions, rotations = pp.calc_projection_shell(32, n_shots=13)
>>> directions.shape, rotations.shape
((32, 3), (13, 3, 3))

The shell runs pole to pole, so the shot rotations leave its ends alone:

>>> bool(np.allclose(directions[[0, -1]], [[0, 0, 1], [0, 0, -1]]))
True

Consecutive views are exactly one step apart, so every turn between them is the same slew:

>>> steps = np.arccos(np.clip(np.sum(directions[:-1] * directions[1:], axis=1), -1, 1))
>>> bool(np.ptp(steps) < 1e-9)
True

See also

calc_golden_angles

in-plane spoke angles, one per shot, for 2D radial.