class_docstr: The `VolumeLocator` class keeps track of the locations of the
  centers of the volume cells in the local volume coordinates as well as in
  the world coordinates for a voxel grid structure in 3D.
  
      Local coordinates:
          - Represent the locations of the volume cells in the local coordinate
            frame of the volume.
          - The center of the voxel indexed with `[·, ·, 0, 0, 0]` in the volume
            has its 3D local coordinate set to `[-1, -1, -1]`, while the voxel
            at index `[·, ·, depth_i-1, height_i-1, width_i-1]` has its
            3D local coordinate set to `[1, 1, 1]`.
          - The first/second/third coordinate of each of the 3D per-voxel
            XYZ vector denotes the horizontal/vertical/depth-wise position
            respectively. I.e the order of the coordinate dimensions in the
            volume is reversed w.r.t. the order of the 3D coordinate vectors.
          - The intermediate coordinates between `[-1, -1, -1]` and `[1, 1, 1]`.
            are linearly interpolated over the spatial dimensions of the volume.
          - Note that the convention is the same as for the 5D version of the
            `torch.nn.functional.grid_sample` function called with
            the same value of `align_corners` argument.
          - Note that the local coordinate convention of `VolumeLocator`
            (+X = left to right, +Y = top to bottom, +Z = away from the user)
            is *different* from the world coordinate convention of the
            renderer for `Meshes` or `Pointclouds`
            (+X = right to left, +Y = bottom to top, +Z = away from the user).
  
      World coordinates:
          - These define the locations of the centers of the volume cells
            in the world coordinates.
          - They are specified with the following mapping that converts
            points `x_local` in the local coordinates to points `x_world`
            in the world coordinates::
  
                  x_world = (
                      x_local * (volume_size - 1) * 0.5 * voxel_size
                  ) - volume_translation,
  
            here `voxel_size` specifies the size of each voxel of the volume,
            and `volume_translation` is the 3D offset of the central voxel of
            the volume w.r.t. the origin of the world coordinate frame.
            Both `voxel_size` and `volume_translation` are specified in
            the world coordinate units. `volume_size` is the spatial size of
            the volume in form of a 3D vector `[width, height, depth]`.
          - Given the above definition of `x_world`, one can derive the
            inverse mapping from `x_world` to `x_local` as follows::
  
                  x_local = (
                      (x_world + volume_translation) / (0.5 * voxel_size)
                  ) / (volume_size - 1)
  
          - For a trivial volume with `volume_translation==[0, 0, 0]`
            with `voxel_size=-1`, `x_world` would range
            from -(volume_size-1)/2` to `+(volume_size-1)/2`.
  
  Coordinate tensors that denote the locations of each of the volume cells in
  local / world coordinates (with shape `(depth x height x width x 3)`)
  can be retrieved by calling the `VolumeLocator.get_coord_grid()` getter with the
  appropriate `world_coordinates` argument.
  
  Internally, the mapping between `x_local` and `x_world` is represented
  as a `Transform3d` object `VolumeLocator._local_to_world_transform`.
  Users can access the relevant transformations with the
  `VolumeLocator.get_world_to_local_coords_transform()` and
  `VolumeLocator.get_local_to_world_coords_transform()`
  functions.
  
  Example coordinate conversion:
      - For a "trivial" volume with `voxel_size = 1.`,
        `volume_translation=[0., 0., 0.]`, and the spatial size of
        `DxHxW = 5x5x5`, the point `x_world = (-2, 0, 2)` gets mapped
        to `x_local=(-1, 0, 1)`.
      - For a "trivial" volume `v` with `voxel_size = 1.`,
        `volume_translation=[0., 0., 0.]`, the following holds::
  
              torch.nn.functional.grid_sample(
                  v.densities(),
                  v.get_coord_grid(world_coordinates=False),
                  align_corners=align_corners,
              ) == v.densities(),
  
          i.e. sampling the volume at trivial local coordinates
          (no scaling with `voxel_size`` or shift with `volume_translation`)
          results in the same volume.
docstr: **batch_size** : Batch size of the underlying grids
  **grid_sizes** : Represents the resolutions of different grids in the batch. Can be
          a) tuple of form (H, W, D)
          b) list/tuple of length batch_size of lists/tuples of form (H, W, D)
          c) torch.Tensor of shape (batch_size, H, W, D)
      H, W, D are height, width, depth respectively.  If `grid_sizes` is a tuple than
      all the  grids in the batch have the same resolution.
  **voxel_size**: Denotes the size of each volume voxel in world units.
      Has to be one of:
      a) A scalar (square voxels)
      b) 3-tuple or a 3-list of scalars
      c) a Tensor of shape (3,)
      d) a Tensor of shape (minibatch, 3)
      e) a Tensor of shape (minibatch, 1)
      f) a Tensor of shape (1,) (square voxels)
  **volume_translation**: Denotes the 3D translation of the center
      of the volume in world units. Has to be one of:
      a) 3-tuple or a 3-list of scalars
      b) a Tensor of shape (3,)
      c) a Tensor of shape (minibatch, 3)
      d) a Tensor of shape (1,) (square voxels)
  **align_corners**: If set (default), the coordinates of the corner voxels are
      exactly −1 or +1 in the local coordinate system. Otherwise, the coordinates
      correspond to the centers of the corner voxels. Cf. the namesake argument to
      `torch.nn.functional.grid_sample`.
docstr_tok: ["*","*","batch_size","*","*",":","Batch","size","of","the","underlying","grids","*","*","grid_sizes","*","*",":","Represents","the","resolutions","of","different","grids","in","the","batch",".","Can","be","a",")","tuple","of","form","(","H",",","W",",","D",")","b",")","list\/tuple","of","length","batch_size","of","lists\/tuples","of","form","(","H",",","W",",","D",")","c",")","torch.Tensor","of","shape","(","batch_size",",","H",",","W",",","D",")","H",",","W",",","D","are","height",",","width",",","depth","respectively",".","If","`","grid_sizes","`","is","a","tuple","than","all","the","grids","in","the","batch","have","the","same","resolution",".","*","*","voxel_size","*","*",":","Denotes","the","size","of","each","volume","voxel","in","world","units",".","Has","to","be","one","of",":","a",")","A","scalar","(","square","voxels",")","b",")","3-tuple","or","a","3-list","of","scalars","c",")","a","Tensor","of","shape","(","3",",",")","d",")","a","Tensor","of","shape","(","minibatch",",","3",")","e",")","a","Tensor","of","shape","(","minibatch",",","1",")","f",")","a","Tensor","of","shape","(","1",",",")","(","square","voxels",")","*","*","volume_translation","*","*",":","Denotes","the","3D","translation","of","the","center","of","the","volume","in","world","units",".","Has","to","be","one","of",":","a",")","3-tuple","or","a","3-list","of","scalars","b",")","a","Tensor","of","shape","(","3",",",")","c",")","a","Tensor","of","shape","(","minibatch",",","3",")","d",")","a","Tensor","of","shape","(","1",",",")","(","square","voxels",")","*","*","align_corners","*","*",":","If","set","(","default",")",",","the","coordinates","of","the","corner","voxels","are","exactly","\u22121","or","+1","in","the","local","coordinate","system",".","Otherwise",",","the","coordinates","correspond","to","the","centers","of","the","corner","voxels",".","Cf",".","the","namesake","argument","to","`","torch.nn.functional.grid_sample","`","."]
code: def __init__(
      self,
      batch_size: int,
      grid_sizes: Union[
          torch.LongTensor, Tuple[int, int, int], List[torch.LongTensor]
      ],
      device: torch.device,
      voxel_size: _VoxelSize = 1.0,
      volume_translation: _Translation = (0.0, 0.0, 0.0),
      align_corners: bool = True,
  ):
      """
      **batch_size** : Batch size of the underlying grids
      **grid_sizes** : Represents the resolutions of different grids in the batch. Can be
              a) tuple of form (H, W, D)
              b) list/tuple of length batch_size of lists/tuples of form (H, W, D)
              c) torch.Tensor of shape (batch_size, H, W, D)
          H, W, D are height, width, depth respectively.  If `grid_sizes` is a tuple than
          all the  grids in the batch have the same resolution.
      **voxel_size**: Denotes the size of each volume voxel in world units.
          Has to be one of:
          a) A scalar (square voxels)
          b) 3-tuple or a 3-list of scalars
          c) a Tensor of shape (3,)
          d) a Tensor of shape (minibatch, 3)
          e) a Tensor of shape (minibatch, 1)
          f) a Tensor of shape (1,) (square voxels)
      **volume_translation**: Denotes the 3D translation of the center
          of the volume in world units. Has to be one of:
          a) 3-tuple or a 3-list of scalars
          b) a Tensor of shape (3,)
          c) a Tensor of shape (minibatch, 3)
          d) a Tensor of shape (1,) (square voxels)
      **align_corners**: If set (default), the coordinates of the corner voxels are
          exactly −1 or +1 in the local coordinate system. Otherwise, the coordinates
          correspond to the centers of the corner voxels. Cf. the namesake argument to
          `torch.nn.functional.grid_sample`.
      """
      self.device = device
      self._batch_size = batch_size
      self._grid_sizes = self._convert_grid_sizes2tensor(grid_sizes)
      self._resolution = tuple(
          torch.max(self._grid_sizes.cpu(), dim=0).values
      )
      self._align_corners = align_corners
  
      # set the local_to_world transform
      self._set_local_to_world_transform(
          voxel_size=voxel_size,
          volume_translation=volume_translation,
      )
  
imports: import copy
  from typing import List, Optional, Tuple, Union
  import torch
  from pytorch3d.common.compat import meshgrid_ij
  from pytorch3d.common.datatypes import Device, make_device
  from pytorch3d.transforms import Scale, Transform3d
  from .None import utils
label_desc: Use image node_id 1 to create a new VolumeLocator object  with example: obj = VolumeLocator(batch_size, grid_sizes, device, voxel_size, volume_translation, align_corners)