docstr: Check that for a list of 2 trivial volumes with
  spatial sizes DxHxW=(5x7x5, 3x5x5):
  1) xyz_world=(0, 0, 0) lands right in the middle of the volume
  with xyz_local=(0, 0, 0).
  2) xyz_world=((-2, 3, -2), (-2, -2,  1)) results
  in xyz_local=((-1, 1, -1), (-1, -1, 1)).
  3) The centeral voxel of the volume coordinate grid
  has coords x_world=(0, 0, 0) and x_local=(0, 0, 0)
  4) grid_sampler(world_coordinate_grid, local_coordinate_grid)
  is the same as world_coordinate_grid itself. I.e. the local coordinate
  grid matches the grid_sampler coordinate convention.
docstr_tok: ["Check","that","for","a","list","of","2","trivial","volumes","with","spatial","sizes","DxHxW=","(","5x7x5",",","3x5x5",")",":","1",")","xyz_world=","(","0",",","0",",","0",")","lands","right","in","the","middle","of","the","volume","with","xyz_local=","(","0",",","0",",","0",")",".","2",")","xyz_world=","(","(","-2",",","3",",","-2",")",",","(","-2",",","-2",",","1",")",")","results","in","xyz_local=","(","(","-1",",","1",",","-1",")",",","(","-1",",","-1",",","1",")",")",".","3",")","The","centeral","voxel","of","the","volume","coordinate","grid","has","coords","x_world=","(","0",",","0",",","0",")","and","x_local=","(","0",",","0",",","0",")","4",")","grid_sampler","(","world_coordinate_grid",",","local_coordinate_grid",")","is","the","same","as","world_coordinate_grid","itself",".","I.e",".","the","local","coordinate","grid","matches","the","grid_sampler","coordinate","convention","."]
code: def test_coord_grid_convention_heterogeneous(
      self, num_channels=4, dtype=torch.float32
  ):
      """
      Check that for a list of 2 trivial volumes with
      spatial sizes DxHxW=(5x7x5, 3x5x5):
      1) xyz_world=(0, 0, 0) lands right in the middle of the volume
      with xyz_local=(0, 0, 0).
      2) xyz_world=((-2, 3, -2), (-2, -2,  1)) results
      in xyz_local=((-1, 1, -1), (-1, -1, 1)).
      3) The centeral voxel of the volume coordinate grid
      has coords x_world=(0, 0, 0) and x_local=(0, 0, 0)
      4) grid_sampler(world_coordinate_grid, local_coordinate_grid)
      is the same as world_coordinate_grid itself. I.e. the local coordinate
      grid matches the grid_sampler coordinate convention.
      """
  
      device = torch.device("cuda:0")
  
      sizes = [(5, 7, 5), (3, 5, 5)]
  
      densities_list = [
          torch.randn(
              size=[num_channels, *size],
              device=device,
              dtype=torch.float32,
          )
          for size in sizes
      ]
  
      # init the volume
      v_trivial = Volumes(densities=densities_list)
  
      # check the border point locations
      pts_world = torch.tensor(
          [[-2.0, 3.0, -2.0], [-2.0, -2.0, 1.0]],
          device=device,
          dtype=torch.float32,
      )[:, None]
      pts_local = v_trivial.world_to_local_coords(pts_world)
      pts_local_expected = torch.tensor(
          [[-1.0, 1.0, -1.0], [-1.0, -1.0, 1.0]],
          device=device,
          dtype=torch.float32,
      )[:, None]
      self.assertClose(pts_local, pts_local_expected)
  
      # check that the central voxel has coords x_world=(0, 0, 0) and x_local(0, 0, 0)
      grid_world = v_trivial.get_coord_grid(world_coordinates=True)
      grid_local = v_trivial.get_coord_grid(world_coordinates=False)
      for grid in (grid_world, grid_local):
          x0 = grid[0, :, :, 2, 0]
          y0 = grid[0, :, 3, :, 1]
          z0 = grid[0, 2, :, :, 2]
          for coord_line in (x0, y0, z0):
              self.assertClose(
                  coord_line, torch.zeros_like(coord_line), atol=1e-7
              )
          x0 = grid[1, :, :, 2, 0]
          y0 = grid[1, :, 2, :, 1]
          z0 = grid[1, 1, :, :, 2]
          for coord_line in (x0, y0, z0):
              self.assertClose(
                  coord_line, torch.zeros_like(coord_line), atol=1e-7
              )
  
      # resample grid_world using grid_sampler with local coords
      # -> make sure the resampled version is the same as original
      for grid_world_, grid_local_, size in zip(
          grid_world, grid_local, sizes
      ):
          grid_world_crop = grid_world_[
              : size[0], : size[1], : size[2], :
          ][None]
          grid_local_crop = grid_local_[
              : size[0], : size[1], : size[2], :
          ][None]
          grid_world_crop_resampled = torch.nn.functional.grid_sample(
              grid_world_crop.permute(0, 4, 1, 2, 3),
              grid_local_crop,
              align_corners=True,
          ).permute(0, 2, 3, 4, 1)
          self.assertClose(
              grid_world_crop_resampled, grid_world_crop, atol=1e-7
          )
  
imports: import copy
  import itertools
  import random
  import unittest
  import numpy
  import torch
  from pytorch3d.structures.volumes import VolumeLocator, Volumes
  from pytorch3d.transforms import Scale
  from .common_testing import TestCaseMixin
label_desc: Use image node_id 8 for calling the TestVolumes obj's underlying member method code with example usage: obj.test_coord_grid_convention_heterogeneous(num_channels, dtype) without return types