code: def _dump_visuals(self, epoch):
      if random.random() < self.opt.vizual_ratio:
          if not hasattr(self, "visual_count"):
              self.visual_count = 0
          data_visual = Data(
              pos=self.raw_pos,
              y=self.input.y,
              instance_labels=self.input.instance_labels,
              batch=self.input.batch,
          )
          data_visual.semantic_pred = torch.max(
              self.output.semantic_logits, -1
          )[1]
          data_visual.vote = self.output.offset_logits
          nms_idx = self.output.get_instances()
          if self.output.clusters is not None:
              data_visual.clusters = [
                  self.output.clusters[i].cpu() for i in nms_idx
              ]
              data_visual.cluster_type = self.output.cluster_type[
                  nms_idx
              ]
          if not os.path.exists("viz"):
              os.mkdir("viz")
          torch.save(
              data_visual.to("cpu"),
              "viz/data_e%i_%i.pt" % (epoch, self.visual_count),
          )
          self.visual_count += 1
  
imports: import torch
  import os
  from torch_points_kernels import region_grow
  from torch_geometric.data import Data
  from torch_scatter import scatter
  import random
  from torch_points3d.datasets.segmentation import IGNORE_LABEL
  from torch_points3d.models.base_model import BaseModel
  from torch_points3d.applications.minkowski import Minkowski
  from torch_points3d.core.common_modules import Seq, MLP, FastBatchNorm1d
  from torch_points3d.core.losses import offset_loss, instance_iou_loss
  from torch_points3d.core.data_transform import GridSampling3D
  from .structures import PanopticLabels, PanopticResults
  from torch_points3d.utils import is_list
label_desc: Use image node_id 8 for calling the PointGroup obj's underlying member method code with example usage: obj._dump_visuals(epoch) without return types