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 _dict_to_structured_npy(self, item):
      item.keys()
      out = []
      dtypes = []
      for k, v in item.items():
          v_npy = v.detach().cpu().numpy()
          if len(v_npy.shape) == 1:
              v_npy = v_npy[..., np.newaxis]
          for dtype in self._saved_keys[k]:
              dtypes.append(dtype)
          out.append(v_npy)
  
      out = np.concatenate(out, axis=-1)
      dtypes = np.dtype([tuple(d) for d in dtypes])
      return np.asarray([tuple(o) for o in out], dtype=dtypes)
  
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 7 for calling the Visualizer obj's underlying member method code with example usage: obj._dict_to_structured_npy(item) and returns: np