docstr: train method (also used for validation monitoring). wrapper around forward pass of network. prepares input data
  for processing, computes losses, and stores outputs in a dictionary.
  :param batch: dictionary containing 'data', 'seg', etc.
  :return: results_dict: dictionary with keys:
          'boxes': list over batch elements. each batch element is a list of boxes. each box is a dictionary:
                  [[{box_0}, ... {box_n}], [{box_0}, ... {box_n}], ...]
          'seg_preds': pixelwise segmentation output (b, c, y, x, (z)) with values [0, .., n_classes].
          'monitor_values': dict of values to be monitored.
docstr_tok: ["train","method","(","also","used","for","validation","monitoring",")",".","wrapper","around","forward","pass","of","network",".","prepares","input","data","for","processing",",","computes","losses",",","and","stores","outputs","in","a","dictionary",".",":","param","batch",":","dictionary","containing","'data","'",",","'seg","'",",","etc",".",":","return",":","results_dict",":","dictionary","with","keys",":","'boxes","'",":","list","over","batch","elements",".","each","batch","element","is","a","list","of","boxes",".","each","box","is","a","dictionary",":","[","[","{","box_0","}",",","...","{","box_n","}","]",",","[","{","box_0","}",",","...","{","box_n","}","]",",","...","]","'seg_preds","'",":","pixelwise","segmentation","output","(","b",",","c",",","y",",","x",",","(","z",")",")","with","values","[","0",",","..",",","n_classes","]",".","'monitor_values","'",":","dict","of","values","to","be","monitored","."]
code: def train_forward(self, batch, **kwargs):
      """
      train method (also used for validation monitoring). wrapper around forward pass of network. prepares input data
      for processing, computes losses, and stores outputs in a dictionary.
      :param batch: dictionary containing 'data', 'seg', etc.
      :return: results_dict: dictionary with keys:
              'boxes': list over batch elements. each batch element is a list of boxes. each box is a dictionary:
                      [[{box_0}, ... {box_n}], [{box_0}, ... {box_n}], ...]
              'seg_preds': pixelwise segmentation output (b, c, y, x, (z)) with values [0, .., n_classes].
              'monitor_values': dict of values to be monitored.
      """
      img = batch["data"]
      gt_class_ids = batch["roi_labels"]
      gt_boxes = batch["bb_target"]
      var_seg_ohe = torch.FloatTensor(
          mutils.get_one_hot_encoding(
              batch["seg"], self.cf.num_seg_classes
          )
      ).cuda()
      var_seg = torch.LongTensor(batch["seg"]).cuda()
  
      img = torch.from_numpy(img).float().cuda()
      batch_class_loss = torch.FloatTensor([0]).cuda()
      batch_bbox_loss = torch.FloatTensor([0]).cuda()
  
      # list of output boxes for monitoring/plotting. each element is a list of boxes per batch element.
      box_results_list = [[] for _ in range(img.shape[0])]
      detections, class_logits, pred_deltas, seg_logits = self.forward(
          img
      )
  
      # loop over batch
      for b in range(img.shape[0]):
          # add gt boxes to results dict for monitoring.
          if len(gt_boxes[b]) > 0:
              for ix in range(len(gt_boxes[b])):
                  box_results_list[b].append(
                      {
                          "box_coords": batch["bb_target"][b][ix],
                          "box_label": batch["roi_labels"][b][ix],
                          "box_type": "gt",
                      }
                  )
  
              # match gt boxes with anchors to generate targets.
              (
                  anchor_class_match,
                  anchor_target_deltas,
              ) = mutils.gt_anchor_matching(
                  self.cf, self.np_anchors, gt_boxes[b], gt_class_ids[b]
              )
  
              # add positive anchors used for loss to results_dict for monitoring.
              pos_anchors = mutils.clip_boxes_numpy(
                  self.np_anchors[np.argwhere(anchor_class_match > 0)][
                      :, 0
                  ],
                  img.shape[2:],
              )
              for p in pos_anchors:
                  box_results_list[b].append(
                      {"box_coords": p, "box_type": "pos_anchor"}
                  )
  
          else:
              anchor_class_match = np.array(
                  [-1] * self.np_anchors.shape[0]
              )
              anchor_target_deltas = np.array([0])
  
          anchor_class_match = torch.from_numpy(
              anchor_class_match
          ).cuda()
          anchor_target_deltas = (
              torch.from_numpy(anchor_target_deltas).float().cuda()
          )
  
          # compute losses.
          class_loss, neg_anchor_ix = compute_class_loss(
              anchor_class_match, class_logits[b]
          )
          bbox_loss = compute_bbox_loss(
              anchor_target_deltas, pred_deltas[b], anchor_class_match
          )
  
          # add negative anchors used for loss to results_dict for monitoring.
          neg_anchors = mutils.clip_boxes_numpy(
              self.np_anchors[np.argwhere(anchor_class_match == -1)][
                  0, neg_anchor_ix
              ],
              img.shape[2:],
          )
          for n in neg_anchors:
              box_results_list[b].append(
                  {"box_coords": n, "box_type": "neg_anchor"}
              )
  
          batch_class_loss += class_loss / img.shape[0]
          batch_bbox_loss += bbox_loss / img.shape[0]
  
      results_dict = get_results(
          self.cf, img.shape, detections, seg_logits, box_results_list
      )
      seg_loss_dice = 1 - mutils.batch_dice(
          F.softmax(seg_logits, dim=1), var_seg_ohe
      )
      seg_loss_ce = F.cross_entropy(seg_logits, var_seg[:, 0])
      loss = (
          batch_class_loss
          + batch_bbox_loss
          + (seg_loss_dice + seg_loss_ce) / 2
      )
      results_dict["torch_loss"] = loss
      results_dict["monitor_values"] = {
          "loss": loss.item(),
          "class_loss": batch_class_loss.item(),
      }
      results_dict[
          "logger_string"
      ] = "loss: {0:.2f}, class: {1:.2f}, bbox: {2:.2f}, seg dice: {3:.3f}, seg ce: {4:.3f}, mean pix. pr.: {5:.5f}".format(
          loss.item(),
          batch_class_loss.item(),
          batch_bbox_loss.item(),
          seg_loss_dice.item(),
          seg_loss_ce.item(),
          np.mean(results_dict["seg_preds"]),
      )
  
      return results_dict
  
imports: import utils.model_utils
  import utils.exp_utils
  import sys
  from cuda_functions.nms_2D.pth_nms import nms_gpu
  from cuda_functions.nms_3D.pth_nms import nms_gpu
  import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  import torch.utils
label_desc: Use image node_id 3 for calling the net obj's underlying member method code with example usage: obj.train_forward(batch) and returns: results_dict