class_docstr: A class for representing and solving predictive models based on
  tractography solutions.
  
  Notes
  -----
  This is an implementation of the LiFE model described in [1]_
  
  [1] Pestilli, F., Yeatman, J, Rokem, A. Kay, K. and Wandell
      B.A. (2014). Validation and statistical inference in living
      connectomes. Nature Methods.
docstr: Set up the necessary components for the LiFE model: the matrix of
  fiber-contributions to the DWI signal, and the coordinates of voxels
  for which the equations will be solved
  
  Parameters
  ----------
  streamline : list
      Streamlines, each is an array of shape (n, 3)
  affine : array_like (4, 4)
      The mapping from voxel coordinates to streamline points.
      The voxel_to_rasmm matrix, typically from a NIFTI file.
  evals : array-like (3 items, optional)
      The eigenvalues of the canonical tensor used as a response
      function. Default:[0.001, 0, 0].
  sphere: `dipy.core.Sphere` instance, optional
      Whether to approximate (and cache) the signal on a discrete
      sphere. This may confer a significant speed-up in setting up the
      problem, but is not as accurate. If `False`, we use the exact
      gradients along the streamlines to calculate the matrix, instead of
      an approximation. Defaults to use the 724-vertex symmetric sphere
      from :mod:`dipy.data`
docstr_tok: ["Set","up","the","necessary","components","for","the","LiFE","model",":","the","matrix","of","fiber-contributions","to","the","DWI","signal",",","and","the","coordinates","of","voxels","for","which","the","equations","will","be","solved","Parameters","--","--","--","--","--","streamline",":","list","Streamlines",",","each","is","an","array","of","shape","(","n",",","3",")","affine",":","array_like","(","4",",","4",")","The","mapping","from","voxel","coordinates","to","streamline","points",".","The","voxel_to_rasmm","matrix",",","typically","from","a","NIFTI","file",".","evals",":","array-like","(","3","items",",","optional",")","The","eigenvalues","of","the","canonical","tensor","used","as","a","response","function",".","Default",":","[","0.001",",","0",",","0","]",".","sphere",":","`","dipy.core.Sphere","`","instance",",","optional","Whether","to","approximate","(","and","cache",")","the","signal","on","a","discrete","sphere",".","This","may","confer","a","significant","speed-up","in","setting","up","the","problem",",","but","is","not","as","accurate",".","If","`","False","`",",","we","use","the","exact","gradients","along","the","streamlines","to","calculate","the","matrix",",","instead","of","an","approximation",".","Defaults","to","use","the","724-vertex","symmetric","sphere","from",":","mod",":","`","dipy.data","`"]
code: def setup(self, streamline, affine, evals=(0.001, 0, 0), sphere=None):
      """
      Set up the necessary components for the LiFE model: the matrix of
      fiber-contributions to the DWI signal, and the coordinates of voxels
      for which the equations will be solved
  
      Parameters
      ----------
      streamline : list
          Streamlines, each is an array of shape (n, 3)
      affine : array_like (4, 4)
          The mapping from voxel coordinates to streamline points.
          The voxel_to_rasmm matrix, typically from a NIFTI file.
      evals : array-like (3 items, optional)
          The eigenvalues of the canonical tensor used as a response
          function. Default:[0.001, 0, 0].
      sphere: `dipy.core.Sphere` instance, optional
          Whether to approximate (and cache) the signal on a discrete
          sphere. This may confer a significant speed-up in setting up the
          problem, but is not as accurate. If `False`, we use the exact
          gradients along the streamlines to calculate the matrix, instead of
          an approximation. Defaults to use the 724-vertex symmetric sphere
          from :mod:`dipy.data`
      """
      if sphere is not False:
          SignalMaker = LifeSignalMaker(
              self.gtab, evals=evals, sphere=sphere
          )
  
      streamline = transform_streamlines(streamline, affine)
      # Assign some local variables, for shorthand:
      all_coords = np.concatenate(streamline)
      vox_coords = unique_rows(np.round(all_coords).astype(np.intp))
      del all_coords
      # We only consider the diffusion-weighted signals:
      n_bvecs = self.gtab.bvals[~self.gtab.b0s_mask].shape[0]
      v2f, v2fn = voxel2streamline(
          streamline, np.eye(4), unique_idx=vox_coords
      )
      # How many fibers in each voxel (this will determine how many
      # components are in the matrix):
      n_unique_f = len(np.hstack(list(v2f.values())))
      # Preallocate these, which will be used to generate the sparse
      # matrix:
      f_matrix_sig = np.zeros(n_unique_f * n_bvecs, dtype=float)
      f_matrix_row = np.zeros(n_unique_f * n_bvecs, dtype=np.intp)
      f_matrix_col = np.zeros(n_unique_f * n_bvecs, dtype=np.intp)
  
      fiber_signal = []
      for s_idx, s in enumerate(streamline):
          if sphere is not False:
              fiber_signal.append(SignalMaker.streamline_signal(s))
          else:
              fiber_signal.append(
                  streamline_signal(s, self.gtab, evals)
              )
  
      del streamline
      if sphere is not False:
          del SignalMaker
  
      keep_ct = 0
      range_bvecs = np.arange(n_bvecs).astype(int)
      # In each voxel:
      for v_idx in range(vox_coords.shape[0]):
          mat_row_idx = (range_bvecs + v_idx * n_bvecs).astype(np.intp)
          # For each fiber in that voxel:
          for f_idx in v2f[v_idx]:
              # For each fiber-voxel combination, store the row/column
              # indices in the pre-allocated linear arrays
              f_matrix_row[keep_ct : keep_ct + n_bvecs] = mat_row_idx
              f_matrix_col[keep_ct : keep_ct + n_bvecs] = f_idx
  
              vox_fiber_sig = np.zeros(n_bvecs)
              for node_idx in v2fn[f_idx][v_idx]:
                  # Sum the signal from each node of the fiber in that voxel:
                  vox_fiber_sig += fiber_signal[f_idx][node_idx]
              # And add the summed thing into the corresponding rows:
              f_matrix_sig[keep_ct : keep_ct + n_bvecs] += vox_fiber_sig
              keep_ct = keep_ct + n_bvecs
  
      del v2f, v2fn
      # Allocate the sparse matrix, using the more memory-efficient 'csr'
      # format:
      life_matrix = sps.csr_matrix(
          (f_matrix_sig, [f_matrix_row, f_matrix_col])
      )
  
      return life_matrix, vox_coords
  
imports: import numpy
  import scipy.sparse
  import scipy.linalg
  from dipy.reconst.base import ReconstModel, ReconstFit
  from dipy.tracking.utils import unique_rows
  from dipy.tracking.streamline import transform_streamlines
  from dipy.tracking.vox2track import _voxel2streamline
  import dipy.data
  import dipy.core.optimize
label_desc: Use image node_id 2 for calling the FiberModel obj's underlying member method code with example usage: obj.setup(streamline, affine, evals, sphere) and returns: life_matrix,  vox_coords