class_docstr: Loss function for HoVerNet pipeline, which is combination of losses across the three branches.
  The NP (nucleus prediction) branch uses Dice + CrossEntropy.
  The HV (Horizontal and Vertical) distance from centroid branch uses MSE + MSE of the gradient.
  The NC (Nuclear Class prediction) branch uses Dice + CrossEntropy
  The result is a weighted sum of these losses.
  
  Args:
      lambda_hv_mse: Weight factor to apply to the HV regression MSE part of the overall loss
      lambda_hv_mse_grad: Weight factor to apply to the MSE of the HV gradient part of the overall loss
      lambda_np_ce: Weight factor to apply to the nuclei prediction CrossEntropyLoss part
          of the overall loss
      lambda_np_dice: Weight factor to apply to the nuclei prediction DiceLoss part of overall loss
      lambda_nc_ce: Weight factor to apply to the nuclei class prediction CrossEntropyLoss part
          of the overall loss
      lambda_nc_dice: Weight factor to apply to the nuclei class prediction DiceLoss part of the
          overall loss
docstr: Args:
      prediction: dictionary of predicted outputs for three branches,
          each of which should have the shape of BNHW.
      target: dictionary of ground truths for three branches,
          each of which should have the shape of BNHW.
docstr_tok: ["Args",":","prediction",":","dictionary","of","predicted","outputs","for","three","branches",",","each","of","which","should","have","the","shape","of","BNHW",".","target",":","dictionary","of","ground","truths","for","three","branches",",","each","of","which","should","have","the","shape","of","BNHW","."]
code: def forward(
      self,
      prediction: dict[str, torch.Tensor],
      target: dict[str, torch.Tensor],
  ) -> torch.Tensor:
      """
      Args:
          prediction: dictionary of predicted outputs for three branches,
              each of which should have the shape of BNHW.
          target: dictionary of ground truths for three branches,
              each of which should have the shape of BNHW.
      """
  
      if not (
          HoVerNetBranch.NP.value in prediction
          and HoVerNetBranch.HV.value in prediction
      ):
          raise ValueError(
              "nucleus prediction (NP) and horizontal_vertical (HV) branches must be "
              "present for prediction and target parameters"
          )
      if not (
          HoVerNetBranch.NP.value in target
          and HoVerNetBranch.HV.value in target
      ):
          raise ValueError(
              "nucleus prediction (NP) and horizontal_vertical (HV) branches must be "
              "present for prediction and target parameters"
          )
      if (
          HoVerNetBranch.NC.value not in target
          and HoVerNetBranch.NC.value in target
      ):
          raise ValueError(
              "type_prediction (NC) must be present in both or neither of the prediction and target parameters"
          )
      if (
          HoVerNetBranch.NC.value in target
          and HoVerNetBranch.NC.value not in target
      ):
          raise ValueError(
              "type_prediction (NC) must be present in both or neither of the prediction and target parameters"
          )
  
      # Compute the NP branch loss
      dice_loss_np = (
          self.dice(
              prediction[HoVerNetBranch.NP.value],
              target[HoVerNetBranch.NP.value],
          )
          * self.lambda_np_dice
      )
      # convert to target class indices
      argmax_target = target[HoVerNetBranch.NP.value].argmax(dim=1)
      ce_loss_np = (
          self.ce(prediction[HoVerNetBranch.NP.value], argmax_target)
          * self.lambda_np_ce
      )
      loss_np = dice_loss_np + ce_loss_np
  
      # Compute the HV branch loss
      loss_hv_mse = (
          F.mse_loss(
              prediction[HoVerNetBranch.HV.value],
              target[HoVerNetBranch.HV.value],
          )
          * self.lambda_hv_mse
      )
  
      # Use the nuclei class, one hot encoded, as the mask
      loss_hv_mse_grad = (
          self._mse_gradient_loss(
              prediction[HoVerNetBranch.HV.value],
              target[HoVerNetBranch.HV.value],
              target[HoVerNetBranch.NP.value][:, 1],
          )
          * self.lambda_hv_mse_grad
      )
      loss_hv = loss_hv_mse_grad + loss_hv_mse
  
      # Compute the NC branch loss
      loss_nc = 0
      if HoVerNetBranch.NC.value in prediction:
          dice_loss_nc = (
              self.dice(
                  prediction[HoVerNetBranch.NC.value],
                  target[HoVerNetBranch.NC.value],
              )
              * self.lambda_nc_dice
          )
          # Convert to target class indices
          argmax_target = target[HoVerNetBranch.NC.value].argmax(dim=1)
          ce_loss_nc = (
              self.ce(
                  prediction[HoVerNetBranch.NC.value], argmax_target
              )
              * self.lambda_nc_ce
          )
          loss_nc = dice_loss_nc + ce_loss_nc
  
      # Sum the losses from each branch
      loss: torch.Tensor = loss_hv + loss_np + loss_nc
  
      return loss
  
file_path: MONAI/monai/apps/pathology/losses/hovernet_loss.py
imports: from __future__ import annotations
  import torch
  from torch.nn import CrossEntropyLoss
  from torch.nn import functional
  from torch.nn.modules.loss import _Loss
  from monai.losses import DiceLoss
  from monai.transforms import SobelGradients
  from monai.utils.enums import HoVerNetBranch
label_desc: Use image node_id 4 for calling the HoVerNetLoss obj's underlying member method code with example usage: obj.forward(prediction, target) and returns: loss