code: def test_save_pointcloud(self):
      header = "\n".join(
          [
              "ply",
              "format binary_little_endian 1.0",
              "element vertex 8",
              "property float x",
              "property float y",
              "property float z",
              "property float red",
              "property float green",
              "property float blue",
              "end_header",
              "",
          ]
      ).encode("ascii")
      data = struct.pack("<" + "f" * 48, *range(48))
      points = (
          torch.FloatTensor([0, 1, 2]) + 6 * torch.arange(8)[:, None]
      )
      features_large = (
          torch.FloatTensor([3, 4, 5]) + 6 * torch.arange(8)[:, None]
      )
      features = features_large / 255.0
      pointcloud_largefeatures = Pointclouds(
          points=[points], features=[features_large]
      )
      pointcloud = Pointclouds(points=[points], features=[features])
  
      io = IO()
      with NamedTemporaryFile(mode="rb", suffix=".ply") as f:
          io.save_pointcloud(data=pointcloud_largefeatures, path=f.name)
          f.flush()
          f.seek(0)
          actual_data = f.read()
          reloaded_pointcloud = io.load_pointcloud(f.name)
  
      self.assertEqual(header + data, actual_data)
      self.assertClose(reloaded_pointcloud.points_list()[0], points)
      self.assertClose(
          reloaded_pointcloud.features_list()[0], features_large
      )
      # Test the load-save cycle leaves file completely unchanged
      with NamedTemporaryFile(mode="rb", suffix=".ply") as f:
          io.save_pointcloud(
              data=reloaded_pointcloud,
              path=f.name,
          )
          f.flush()
          f.seek(0)
          data2 = f.read()
          self.assertEqual(data2, actual_data)
  
      with NamedTemporaryFile(mode="r", suffix=".ply") as f:
          io.save_pointcloud(
              data=pointcloud,
              path=f.name,
              binary=False,
              decimal_places=9,
          )
          reloaded_pointcloud2 = io.load_pointcloud(f.name)
          self.assertEqual(f.readline(), "ply\n")
          self.assertEqual(f.readline(), "format ascii 1.0\n")
      self.assertClose(reloaded_pointcloud2.points_list()[0], points)
      self.assertClose(
          reloaded_pointcloud2.features_list()[0], features
      )
  
      for binary in [True, False]:
          with NamedTemporaryFile(mode="rb", suffix=".ply") as f:
              io.save_pointcloud(
                  data=pointcloud,
                  path=f.name,
                  colors_as_uint8=True,
                  binary=binary,
              )
              f.flush()
              f.seek(0)
              actual_data = f.read()
              reloaded_pointcloud3 = io.load_pointcloud(f.name)
          self.assertClose(
              reloaded_pointcloud3.features_list()[0], features
          )
          self.assertIn(b"property uchar green", actual_data)
  
          # Test the load-save cycle leaves file completely unchanged
          with NamedTemporaryFile(mode="rb", suffix=".ply") as f:
              io.save_pointcloud(
                  data=reloaded_pointcloud3,
                  path=f.name,
                  binary=binary,
                  colors_as_uint8=True,
              )
              f.flush()
              f.seek(0)
              data2 = f.read()
              self.assertEqual(data2, actual_data)
  
imports: import itertools
  import struct
  import unittest
  from io import BytesIO, StringIO
  from tempfile import NamedTemporaryFile, TemporaryFile
  import numpy
  import pytorch3d.io.ply_io
  import torch
  from iopath.common.file_io import PathManager
  from pytorch3d.io import IO
  from pytorch3d.io.ply_io import load_ply, save_ply
  from pytorch3d.renderer.mesh import TexturesVertex
  from pytorch3d.structures import Meshes, Pointclouds
  from pytorch3d.utils import torus
  from .common_testing import get_tests_dir, TestCaseMixin
label_desc: Use image node_id 18 for calling the TestMeshPlyIO obj's underlying member method code with example usage: obj.test_save_pointcloud() without return types