code: def compute_box_and_sem_cls_loss(
      inputs, outputs, loss_params, weight_classes=None
  ):
      """Compute 3D bounding box and semantic classification loss.
  
      Args:
          end_points: dict (read-only)
  
      Returns:
          center_loss
          heading_cls_loss
          heading_reg_loss
          size_cls_loss
          size_reg_loss
          sem_cls_loss
      """
  
      num_heading_bin = loss_params.num_heading_bin
      mean_size_arr = np.asarray(loss_params.mean_size_arr)
      num_size_cluster = len(mean_size_arr)
  
      object_assignment = outputs.object_assignment
      batch_size = object_assignment.shape[0]
  
      # Compute center loss
      pred_center = outputs["center"]
      gt_center = inputs["gt_center"]
      dist1, ind1, dist2, _ = nn_distance(
          pred_center, gt_center
      )  # dist1: BxK, dist2: BxK2
      box_label_mask = inputs["box_label_mask"]
      objectness_label = outputs["objectness_label"].float()
      centroid_reg_loss1 = torch.sum(dist1 * objectness_label) / (
          torch.sum(objectness_label) + 1e-6
      )
      centroid_reg_loss2 = torch.sum(dist2 * box_label_mask) / (
          torch.sum(box_label_mask) + 1e-6
      )
      center_loss = centroid_reg_loss1 + centroid_reg_loss2
  
      # Compute heading loss
      heading_class_label = torch.gather(
          inputs["heading_class_label"], 1, object_assignment
      )  # select (B,K) from (B,K2)
      criterion_heading_class = nn.CrossEntropyLoss(reduction="none")
  
      heading_class_loss = criterion_heading_class(
          outputs["heading_scores"].transpose(2, 1),
          heading_class_label.long(),
      )  # (B,K)
      heading_class_loss = torch.sum(
          heading_class_loss * objectness_label
      ) / (torch.sum(objectness_label) + 1e-6)
  
      heading_residual_label = torch.gather(
          inputs["heading_residual_label"], 1, object_assignment
      )  # select (B,K) from (B,K2)
      heading_residual_normalized_label = heading_residual_label / (
          np.pi / num_heading_bin
      )
  
      # Ref: https://discuss.pytorch.org/t/convert-int-into-one-hot-format/507/3
      heading_label_one_hot = torch.zeros(
          batch_size, heading_class_label.shape[1], num_heading_bin
      ).to(inputs.pos.device)
      heading_label_one_hot.scatter_(
          2, heading_class_label.unsqueeze(-1).long(), 1
      )  # src==1 so it's *one-hot* (B,K,num_heading_bin) TODO change that for pytorch OneHot
      heading_residual_normalized_loss = huber_loss(
          torch.sum(
              outputs["heading_residuals_normalized"]
              * heading_label_one_hot,
              -1,
          )
          - heading_residual_normalized_label,
          delta=1.0,
      )  # (B,K)
      heading_residual_normalized_loss = torch.sum(
          heading_residual_normalized_loss * objectness_label
      ) / (torch.sum(objectness_label) + 1e-6)
  
      # Compute size loss
      size_class_label = torch.gather(
          inputs["size_class_label"], 1, object_assignment
      )  # select (B,K) from (B,K2)
      criterion_size_class = nn.CrossEntropyLoss(reduction="none")
      if num_size_cluster != 0:
          size_class_loss = criterion_size_class(
              outputs["size_scores"].transpose(2, 1),
              size_class_label.long(),
          )  # (B,K)
          size_class_loss = torch.sum(
              size_class_loss * objectness_label
          ) / (torch.sum(objectness_label) + 1e-6)
  
          size_residual_label = torch.gather(
              inputs["size_residual_label"],
              1,
              object_assignment.unsqueeze(-1).repeat(1, 1, 3),
          )  # select (B,K,3) from (B,K2,3)
  
          size_label_one_hot = torch.zeros(
              batch_size, size_class_label.shape[1], num_size_cluster
          ).to(inputs.pos.device)
          size_label_one_hot.scatter_(
              2, size_class_label.unsqueeze(-1).long(), 1
          )  # src==1 so it's *one-hot* (B,K,num_size_cluster)
          size_label_one_hot_tiled = (
              size_label_one_hot.unsqueeze(-1)
              .repeat(1, 1, 1, 3)
              .contiguous()
          )  # (B,K,num_size_cluster,3)
          predicted_size_residual_normalized = torch.sum(
              outputs["size_residuals_normalized"].contiguous()
              * size_label_one_hot_tiled,
              2,
          )  # (B,K,3)
  
          mean_size_arr_expanded = (
              torch.from_numpy(mean_size_arr.astype(np.float32))
              .unsqueeze(0)
              .unsqueeze(0)
              .to(inputs.pos.device)
          )  # (1,1,num_size_cluster,3)
          mean_size_label = torch.sum(
              size_label_one_hot_tiled * mean_size_arr_expanded, 2
          )  # (B,K,3)
          size_residual_label_normalized = (
              size_residual_label / mean_size_label
          )  # (B,K,3)
          size_residual_normalized_loss = torch.mean(
              huber_loss(
                  predicted_size_residual_normalized
                  - size_residual_label_normalized,
                  delta=1.0,
              ),
              -1,
          )  # (B,K,3) -> (B,K)
          size_residual_normalized_loss = torch.sum(
              size_residual_normalized_loss * objectness_label
          ) / (torch.sum(objectness_label) + 1e-6)
      else:
          size_class_loss = 0
          size_residual_normalized_loss = 0
  
      # 3.4 Semantic cls loss
      sem_cls_label = torch.gather(
          inputs["sem_cls_label"], 1, object_assignment
      )  # select (B,K) from (B,K2)
      criterion_sem_cls = nn.CrossEntropyLoss(
          weight=weight_classes, reduction="none"
      )
      sem_cls_loss = criterion_sem_cls(
          outputs["sem_cls_scores"].transpose(2, 1),
          sem_cls_label.long(),
      )  # (B,K)
      sem_cls_loss = torch.sum(sem_cls_loss * objectness_label) / (
          torch.sum(objectness_label) + 1e-6
      )
  
      return (
          center_loss,
          heading_class_loss,
          heading_residual_normalized_loss,
          size_class_loss,
          size_residual_normalized_loss,
          sem_cls_loss,
      )
  
file_path: torch-points3d/torch_points3d/modules/VoteNet/loss_helper.py
imports: import torch
  import torch.nn
  import numpy
  from torch_points3d.core.losses import huber_loss, nn_distance
  from .votenet_results import VoteNetResults
label_desc: Use image node_id 3 for calling a global function with example usage: compute_box_and_sem_cls_loss(inputs, outputs, loss_params, weight_classes) and returns: center_loss,  heading_class_loss,  heading_residual_normalized_loss,  size_class_loss,  size_residual_normalized_loss,  sem_cls_loss