code: def loop(self, data, gr, sparse, msg):
      shapes = []
      u = data.clone()
      for i in range(2):
          u = gr(u)
          shapes.append(u.pos.shape[0])
  
      data = sparse(u)
      num_points = np.unique(data.pos, axis=0).shape[0]
  
      shapes.append(num_points)
      self.assertEqual(shapes, [shapes[0] for _ in range(len(shapes))])
  
file_path: torch-points3d/test/test_grid_sampling.py
imports: import os
  import sys
  import numpy
  import torch
  import unittest
  import h5py
  import numpy.testing
  import numpy.matlib
  from torch_geometric.data import Data
  import torch_points3d.core.data_transform
label_desc: Use image node_id 3 for calling the TestGridSampling3D obj's underlying member method code with example usage: obj.loop(data, gr, sparse, msg) without return types