code: def _add_votes(self, data, outputs, batch_idx):
      nb_batches = batch_idx.max() + 1
      for b in range(nb_batches):
          batch_mask = b
          if self._conv_type != "DENSE":
              batch_mask = batch_idx == b
          segl = data.y[batch_mask][0].item()
  
          cat = self._seg_to_class[segl]
          logits = outputs[
              batch_idx == b, :
          ]  # (num_points, num_classes)
  
          id_scan = data.id_scan[b].item()
          if id_scan not in self._full_res_scans[cat]:
              raw_data = self._dataset.get_raw_data(
                  self._stage, id_scan
              )
              self._full_res_scans[cat][id_scan] = SegmentationVoter(
                  raw_data,
                  self._num_classes,
                  self._conv_type,
                  class_seg_map=self._class_seg_map[cat],
              )
          self._full_res_scans[cat][id_scan].add_vote(
              data, logits, batch_mask
          )
  
file_path: torch-points3d/torch_points3d/metrics/shapenet_part_tracker.py
imports: import numpy
  from .confusion_matrix import ConfusionMatrix
  from .base_tracker import meter_value, BaseTracker
  from torch_geometric.data import Data
  from torch_points3d.models import model_interface
  from torch_points3d.core.data_transform import SaveOriginalPosId
  from torch_points3d.metrics.segmentation_helpers import SegmentationVoter
label_desc: Use image node_id 4 for calling the ShapenetPartTracker obj's underlying member method code with example usage: obj._add_votes(data, outputs, batch_idx) without return types