class_docstr: A regularly-spaced image for embedding data in an x, y, z 3D
  world, for neuroimaging.
  
  This object is an ndarray representing a volume, with the first 3
  dimensions being spatial, and mapped to a named world space using
  an affine (4x4 matrix).
  
  Attributes
  ----------
  
  affine : 4x4 ndarray
      Affine mapping from indices to world coordinates.
  world_space : string
      Name of the world space the data is embedded in. For
      instance `mni152`.
  metadata : dictionary
      Optional, user-defined, dictionary used to carry around
      extra information about the data as it goes through
      transformations. The consistency of this information may not
      be maintained as the data is modified.
  interpolation : 'continuous' or 'nearest'
      String giving the interpolation logic used when calculating
      values in different world spaces
  _data :
      Private pointer to the data.
  
  Notes
  ------
  
  The data is stored in an undefined way: prescalings might need to
  be applied to it before using it, or the data might be loaded on
  demand. The best practice to access the data is not to access the
  _data attribute, but to use the `get_fdata` method.
class_docstr_tok: ["A","regularly-spaced","image","for","embedding","data","in","an","x",",","y",",","z","3D","world",",","for","neuroimaging",".","This","object","is","an","ndarray","representing","a","volume",",","with","the","first","3","dimensions","being","spatial",",","and","mapped","to","a","named","world","space","using","an","affine","(","4x4","matrix",")",".","Attributes","--","--","--","--","--","affine",":","4x4","ndarray","Affine","mapping","from","indices","to","world","coordinates",".","world_space",":","string","Name","of","the","world","space","the","data","is","embedded","in",".","For","instance","`","mni152","`",".","metadata",":","dictionary","Optional",",","user-defined",",","dictionary","used","to","carry","around","extra","information","about","the","data","as","it","goes","through","transformations",".","The","consistency","of","this","information","may","not","be","maintained","as","the","data","is","modified",".","interpolation",":","'continuous","'","or","'nearest'","String","giving","the","interpolation","logic","used","when","calculating","values","in","different","world","spaces","_data",":","Private","pointer","to","the","data",".","Notes","--","--","--","The","data","is","stored","in","an","undefined","way",":","prescalings","might","need","to","be","applied","to","it","before","using","it",",","or","the","data","might","be","loaded","on","demand",".","The","best","practice","to","access","the","data","is","not","to","access","the","_data","attribute",",","but","to","use","the","`","get_fdata","`","method","."]
code: def as_volume_img(
      self, affine=None, shape=None, interpolation=None, copy=True
  ):
      if affine is None and shape is None:
          if copy:
              import copy
  
              return copy.copy(self)
          else:
              return self
      if affine is None:
          affine = self.affine
      data = self.get_fdata()
      if shape is None:
          shape = data.shape[:3]
      shape = list(shape)
      if affine.shape[0] == 3:
          # We have a 3D affine, we need to find out the offset and
          # shape to keep the same bounding box in the new space
          affine4d = np.eye(4)
          affine4d[:3, :3] = affine
          transform_affine = np.dot(
              np.linalg.inv(affine4d),
              self.affine,
          )
          # The bounding box in the new world, if no offset is given
          (xmin, xmax), (ymin, ymax), (zmin, zmax) = get_bounds(
              data.shape[:3],
              transform_affine,
          )
  
          offset = np.array((xmin, ymin, zmin))
          offset = np.dot(affine, offset)
          affine = from_matrix_vector(affine, offset[:3])
          shape = (
              np.ceil(xmax - xmin) + 1,
              np.ceil(ymax - ymin) + 1,
              np.ceil(zmax - zmin) + 1,
          )
      shape = [int(s) for s in shape]
      if not len(shape) == 3:
          raise ValueError(
              "The shape specified should be the shape "
              "the 3D grid, and thus of length 3. %s was specified"
              % shape
          )
      interpolation_order = self._get_interpolation_order(interpolation)
      if np.all(affine == self.affine):
          # Small trick to be more numericaly stable
          transform_affine = np.eye(4)
      else:
          transform_affine = np.dot(np.linalg.inv(self.affine), affine)
      A, b = to_matrix_vector(transform_affine)
      A_inv = np.linalg.inv(A)
      # If A is diagonal, ndimage.affine_transform is clever-enough
      # to use a better algorithm
      if np.all(np.diag(np.diag(A)) == A):
          A = np.diag(A)
      else:
          b = np.dot(A, b)
      # For images with dimensions larger than 3D:
      data_shape = list(data.shape)
      if len(data_shape) > 3:
          # Iter in a set of 3D volumes, as the interpolation problem is
          # separable in the extra dimensions. This reduces the
          # computational cost
          data = np.reshape(data, data_shape[:3] + [-1])
          data = np.rollaxis(data, 3)
          resampled_data = [
              ndimage.affine_transform(
                  slice,
                  A,
                  offset=np.dot(A_inv, b),
                  output_shape=shape,
                  order=interpolation_order,
              )
              for slice in data
          ]
          resampled_data = np.concatenate(
              [d[..., np.newaxis] for d in resampled_data], axis=3
          )
          resampled_data = np.reshape(
              resampled_data, list(shape) + list(data_shape[3:])
          )
      else:
          resampled_data = ndimage.affine_transform(
              data,
              A,
              offset=np.dot(A_inv, b),
              output_shape=shape,
              order=interpolation_order,
          )
      return self.__class__(
          resampled_data,
          affine,
          self.world_space,
          metadata=self.metadata,
          interpolation=self.interpolation,
      )
  
imports: import copy
  import numpy
  from scipy import ndimage
  from ..transforms.affine_transform import AffineTransform
  from ..transforms.affine_utils import from_matrix_vector, get_bounds, to_matrix_vector
  from ..transforms.transform import CompositionError
  from .volume_grid import VolumeGrid
label_desc: Use image node_id 6 for calling the VolumeImg obj's underlying member method code with example usage: obj.as_volume_img(affine, shape, interpolation, copy) and returns: self, copy, self