code: def test_affine_transformations():
      """This tests that the input affine is properly handled by
      LocalTracking and produces reasonable streamlines in a simple example.
      """
      sphere = HemiSphere.from_sphere(unit_octahedron)
  
      # A simple image with three possible configurations, a vertical tract,
      # a horizontal tract and a crossing
      pmf_lookup = np.array(
          [
              [0.0, 0.0, 1.0],
              [1.0, 0.0, 0.0],
              [0.0, 1.0, 0.0],
              [0.4, 0.6, 0.0],
          ]
      )
      simple_image = np.array(
          [
              [0, 0, 0, 0, 0, 0],
              [0, 1, 0, 0, 0, 0],
              [0, 3, 2, 2, 2, 0],
              [0, 1, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0],
          ]
      )
  
      simple_image = simple_image[..., None]
      pmf = pmf_lookup[simple_image]
  
      seeds = [np.array([1.0, 1.0, 0.0]), np.array([2.0, 4.0, 0.0])]
  
      expected = [
          np.array([[1.0, 1.0, 0.0], [2.0, 1.0, 0.0], [3.0, 1.0, 0.0]]),
          np.array(
              [
                  [2.0, 1.0, 0.0],
                  [2.0, 2.0, 0.0],
                  [2.0, 3.0, 0.0],
                  [2.0, 4.0, 0.0],
              ]
          ),
      ]
  
      mask = (simple_image > 0).astype(float)
      sc = BinaryStoppingCriterion(mask)
  
      dg = DeterministicMaximumDirectionGetter.from_pmf(
          pmf, 60, sphere, pmf_threshold=0.1
      )
  
      # TST- bad affine wrong shape
      bad_affine = np.eye(3)
      npt.assert_raises(
          ValueError, LocalTracking, dg, sc, seeds, bad_affine, 1.0
      )
  
      # TST - bad affine with shearing
      bad_affine = np.eye(4)
      bad_affine[0, 1] = 1.0
      npt.assert_raises(
          ValueError, LocalTracking, dg, sc, seeds, bad_affine, 1.0
      )
  
      # TST - bad seeds
      bad_seeds = 1000
      npt.assert_raises(
          ValueError, LocalTracking, dg, sc, bad_seeds, np.eye(4), 1.0
      )
  
      # TST - identity
      a0 = np.eye(4)
      # TST - affines with positive/negative offsets
      a1 = np.eye(4)
      a1[:3, 3] = [1, 2, 3]
      a2 = np.eye(4)
      a2[:3, 3] = [-2, 0, -1]
      # TST - affine with scaling
      a3 = np.eye(4)
      a3[0, 0] = a3[1, 1] = a3[2, 2] = 8
      # TST - affine with axes inverting (negative value)
      a4 = np.eye(4)
      a4[1, 1] = a4[2, 2] = -1
      # TST - combined affines
      a5 = a1 + a2 + a3
      a5[3, 3] = 1
      # TST - in vivo affine example
      # Sometimes data have affines with tiny shear components.
      # For example, the small_101D data-set has some of that:
      fdata, _, _ = get_fnames("small_101D")
      a6 = nib.load(fdata).affine
  
      for affine in [a0, a1, a2, a3, a4, a5, a6]:
          lin = affine[:3, :3]
          offset = affine[:3, 3]
          seeds_trans = [np.dot(lin, s) + offset for s in seeds]
  
          # We compute the voxel size to adjust the step size to one voxel
          voxel_size = np.mean(np.sqrt(np.dot(lin, lin).diagonal()))
  
          streamlines = LocalTracking(
              direction_getter=dg,
              stopping_criterion=sc,
              seeds=seeds_trans,
              affine=affine,
              step_size=voxel_size,
              return_all=True,
          )
  
          # We apply the inverse affine transformation to the generated
          # streamlines. It should be equals to the expected streamlines
          # (generated with the identity affine matrix).
          affine_inv = np.linalg.inv(affine)
          lin = affine_inv[:3, :3]
          offset = affine_inv[:3, 3]
          streamlines_inv = []
          for line in streamlines:
              streamlines_inv.append(
                  [np.dot(pts, lin) + offset for pts in line]
              )
  
          npt.assert_equal(len(streamlines_inv[0]), len(expected[0]))
          npt.assert_(
              np.allclose(streamlines_inv[0], expected[0], atol=0.3)
          )
          npt.assert_equal(len(streamlines_inv[1]), len(expected[1]))
          npt.assert_(
              np.allclose(streamlines_inv[1], expected[1], atol=0.3)
          )
  
imports: from logging import warn
  import warnings
  import nibabel
  import numpy
  import numpy.testing
  from dipy.core.gradients import gradient_table
  from dipy.core.sphere import HemiSphere, unit_octahedron
  from dipy.data import get_fnames, get_sphere
  from dipy.direction import BootDirectionGetter, ClosestPeakDirectionGetter, DeterministicMaximumDirectionGetter, PeaksAndMetrics, ProbabilisticDirectionGetter, PTTDirectionGetter
  from dipy.reconst.csdeconv import ConstrainedSphericalDeconvModel
  from dipy.reconst.shm import descoteaux07_legacy_msg
  from dipy.tracking.local_tracking import LocalTracking, ParticleFilteringTracking
  from dipy.tracking.streamline import Streamlines
  from dipy.tracking.stopping_criterion import ActStoppingCriterion, BinaryStoppingCriterion, ThresholdStoppingCriterion, StreamlineStatus
  from dipy.tracking.utils import random_seeds_from_mask, seeds_from_mask
  from dipy.sims.voxel import single_tensor, multi_tensor
  from dipy.testing.decorators import set_random_number_generator
label_desc: Use image node_id 11 for calling a global function with example usage: test_affine_transformations() without return types