class_docstr: Initialize the Visualizer class.
  Parameters:
      viz_conf (OmegaConf Dictionnary) -- stores all config for the visualizer
      num_batches (dict) -- This dictionnary maps stage_name to #batches
      batch_size (int) -- Current batch size usef
      save_dir (str) -- The path used by hydra to store the experiment
  
  This class is responsible to save visuals into different formats. Currently supported formats are:
      ply -- Either an ascii or binary ply file, with the labels and gt stored as columns
      tensorboard -- Visualize point cloud in tensorboard
      las -- Export to an ASPRS las or laz file. gt and predictions are stored in seperate files.
      wandb -- Upload point cloud to wandb. WARNING: This can become very slow, both in training and on the web.
          Make sure you properly limit the num_samples_per_epoch and wandb_max_points.
  
  The configuration looks like this:
      visualization:
          activate: False # Whether to activate the visualizer
          format: ["ply", "tensorboard"] # 'pointcloud' is deprecated, use 'ply' instead
          num_samples_per_epoch: 2 # If negative, it will save all elements
          deterministic: True # False -> Randomly sample elements from epoch to epoch
          deterministic_seed: 0 # Random seed used to generate consistant keys if deterministic is True
          saved_keys: # Mapping from Data Object to structured numpy
              pos: [['x', 'float'], ['y', 'float'], ['z', 'float']]
              y: [['l', 'float']]
              pred: [['p', 'float']]
          indices: # List of indices to be saved (support "train", "test", "val")
              train: [0, 3]
          # Format specific options:
          ply_format: binary_big_endian # PLY format (support "binary_big_endian", "binary_little_endian", "ascii")
          tensorboard_mesh: # Mapping from mesh name and propety use to color
              label: 'y'
              prediction: 'pred'
          wandb_max_points: 10000 # Limits the size of the cloud that gets uploaded by random sampling.
                                  # "-1" saves the entire cloud
          wandb_cmap: # Applies a color map to the point cloud. Allows custom coloring of different classes.
              - [0, 0, 0] # class 0
              - [255, 255, 255] # class 1
              - [128, 128, 128] # class 2
          compress_las: True # If true, the point cloud will be output as an "laz" file
class_docstr_tok: ["Initialize","the","Visualizer","class",".","Parameters",":","viz_conf","(","OmegaConf","Dictionnary",")","--","stores","all","config","for","the","visualizer","num_batches","(","dict",")","--","This","dictionnary","maps","stage_name","to","#","batches","batch_size","(","int",")","--","Current","batch","size","usef","save_dir","(","str",")","--","The","path","used","by","hydra","to","store","the","experiment","This","class","is","responsible","to","save","visuals","into","different","formats",".","Currently","supported","formats","are",":","ply","--","Either","an","ascii","or","binary","ply","file",",","with","the","labels","and","gt","stored","as","columns","tensorboard","--","Visualize","point","cloud","in","tensorboard","las","--","Export","to","an","ASPRS","las","or","laz","file",".","gt","and","predictions","are","stored","in","seperate","files",".","wandb","--","Upload","point","cloud","to","wandb",".","WARNING",":","This","can","become","very","slow",",","both","in","training","and","on","the","web",".","Make","sure","you","properly","limit","the","num_samples_per_epoch","and","wandb_max_points",".","The","configuration","looks","like","this",":","visualization",":","activate",":","False","#","Whether","to","activate","the","visualizer","format",":","[","``","ply","''",",","``","tensorboard","''","]","#","'pointcloud","'","is","deprecated",",","use","'ply","'","instead","num_samples_per_epoch",":","2","#","If","negative",",","it","will","save","all","elements","deterministic",":","True","#","False","-",">","Randomly","sample","elements","from","epoch","to","epoch","deterministic_seed",":","0","#","Random","seed","used","to","generate","consistant","keys","if","deterministic","is","True","saved_keys",":","#","Mapping","from","Data","Object","to","structured","numpy","pos",":","[","[","'","x","'",",","'float","'","]",",","[","'","y","'",",","'float","'","]",",","[","'","z","'",",","'float","'","]","]","y",":","[","[","'","l","'",",","'float","'","]","]","pred",":","[","[","'","p","'",",","'float","'","]","]","indices",":","#","List","of","indices","to","be","saved","(","support","``","train","''",",","``","test","''",",","``","val","''",")","train",":","[","0",",","3","]","#","Format","specific","options",":","ply_format",":","binary_big_endian","#","PLY","format","(","support","``","binary_big_endian","''",",","``","binary_little_endian","''",",","``","ascii","''",")","tensorboard_mesh",":","#","Mapping","from","mesh","name","and","propety","use","to","color","label",":","'","y'","prediction",":","'pred'","wandb_max_points",":","10000","#","Limits","the","size","of","the","cloud","that","gets","uploaded","by","random","sampling",".","#","``","-1","''","saves","the","entire","cloud","wandb_cmap",":","#","Applies","a","color","map","to","the","point","cloud",".","Allows","custom","coloring","of","different","classes",".","-","[","0",",","0",",","0","]","#","class","0","-","[","255",",","255",",","255","]","#","class","1","-","[","128",",","128",",","128","]","#","class","2","compress_las",":","True","#","If","true",",","the","point","cloud","will","be","output","as","an","``","laz","''","file"]
code: def __init__(
      self, viz_conf, num_batches, batch_size, save_dir, tracker
  ):
      # From configuration and dataset
      for stage_name, stage_num_sample in num_batches.items():
          setattr(
              self,
              "{}_num_batches".format(stage_name),
              stage_num_sample,
          )
      self._batch_size = batch_size
      self._activate = viz_conf.activate
      self._format = (
          [viz_conf.format]
          if not is_list(viz_conf.format)
          else viz_conf.format
      )
      self._num_samples_per_epoch = int(viz_conf.num_samples_per_epoch)
      self._deterministic = viz_conf.deterministic
      self._seed = (
          viz_conf.deterministic_seed
          if viz_conf.deterministic_seed is not None
          else 0
      )
      self._tracker = tracker
  
      self._saved_keys = viz_conf.saved_keys
      self._tensorboard_mesh = {}
      self._viz_path = os.path.join(save_dir, "viz")
  
      # Internal state
      self._stage = None
      self._current_epoch = None
  
      # format-specific initialization
      if "pointcloud" in self._format:
          log.warning(
              'Visualization format "pointcloud" is deprecated, use "ply" instead.'
          )
      is_ply = "pointcloud" in self._format or "ply" in self._format
  
      if is_ply:
          self._ply_format = (
              viz_conf.ply_format
              if viz_conf.ply_format is not None
              else "binary_big_endian"
          )
  
      if "tensorboard" in self._format:
          if not tracker._use_tensorboard:
              log.warn(
                  "Tensorboard visualization specified, but tensorboard isn't active."
              )
          else:
              self._tensorboard_mesh = viz_conf.tensorboard_mesh
  
              # SummaryWriter for tensorboard loging
              self._writer = tracker._writer
  
      if "wandb" in self._format:
          if not self._tracker._wandb:
              log.warn(
                  "Wandb visualization specified, but Wandb isn't active."
              )
          else:
              self._wandb_cmap = viz_conf.wandb_cmap
              self._max_points = (
                  viz_conf.wandb_max_points
                  if viz_conf.wandb_max_points is not None
                  else -1
              )
  
      if "las" in self._format:
          self._las_compress = (
              viz_conf.compress_las
              if viz_conf.compress_las is not None
              else False
          )
  
      self._indices = {}
      self._contains_indices = False
  
      try:
          indices = getattr(viz_conf, "indices", None)
      except:
          indices = None
  
      if indices:
          for split in ["train", "test", "val"]:
              if split in indices:
                  split_indices = indices[split]
                  self._indices[split] = np.asarray(split_indices)
                  self._contains_indices = True
  
imports: import os
  import torch
  import numpy
  from plyfile import PlyData, PlyElement
  import logging
  import wandb
  from itertools import product
  from matplotlib.cm import get_cmap
  from math import log10, ceil
  from torch_points3d.utils.config import is_list
label_desc: Use image node_id 1 to create a new Visualizer object from inherited base classes: object with example: obj = Visualizer(viz_conf, num_batches, batch_size, save_dir, tracker)