code: def proposal_layer(
      rpn_pred_probs, rpn_pred_deltas, proposal_count, anchors, cf
  ):
      """
      Receives anchor scores and selects a subset to pass as proposals
      to the second stage. Filtering is done based on anchor scores and
      non-max suppression to remove overlaps. It also applies bounding
      box refinment detals to anchors.
      :param rpn_pred_probs: (b, n_anchors, 2)
      :param rpn_pred_deltas: (b, n_anchors, (y, x, (z), log(h), log(w), (log(d))))
      :return: batch_normalized_boxes: Proposals in normalized coordinates
      (b, proposal_count, (y1, x1, y2, x2, (z1), (z2)))
      :return: batch_out_proposals: Box coords + RPN foreground scores
      for monitoring/plotting (b, proposal_count, (y1, x1, y2, x2, (z1), (z2), score))
      """
      batch_scores = rpn_pred_probs[:, :, 1]
      batch_deltas = rpn_pred_deltas
      batch_anchors = anchors
      batch_normalized_boxes = []
      batch_out_proposals = []
  
      # loop over batch dimension.
      for ix in range(batch_scores.shape[0]):
          scores = batch_scores[ix]
          deltas = batch_deltas[ix]
          anchors = batch_anchors.clone()
          # norm deltas
          std_dev = (
              torch.from_numpy(cf.rpn_bbox_std_dev[None]).float().cuda()
          )
          deltas = deltas * std_dev
  
          # improve performance by trimming to top anchors by score
          # and doing the rest on the smaller subset.
          pre_nms_limit = min(cf.pre_nms_limit, anchors.size()[0])
          scores, order = scores.sort(descending=True)
          order = order[:pre_nms_limit]
          scores = scores[:pre_nms_limit]
          deltas = deltas[order, :]
          anchors = anchors[order, :]
  
          # apply deltas to anchors to get refined anchors and filter with non-maximum surpression.
          if batch_deltas.shape[-1] == 4:
              boxes = mutils.apply_box_deltas_2D(anchors, deltas)
              boxes = mutils.clip_boxes_2D(boxes, cf.window)
              keep = nms_2D(
                  torch.cat((boxes, scores.unsqueeze(1)), 1),
                  cf.rpn_nms_threshold,
              )
              norm = torch.from_numpy(cf.scale).float().cuda()
  
          else:
              boxes = mutils.apply_box_deltas_3D(anchors, deltas)
              boxes = mutils.clip_boxes_3D(boxes, cf.window)
              keep = nms_3D(
                  torch.cat((boxes, scores.unsqueeze(1)), 1),
                  cf.rpn_nms_threshold,
              )
              norm = torch.from_numpy(cf.scale).float().cuda()
  
          keep = keep[:proposal_count]
          boxes = boxes[keep, :]
          rpn_scores = scores[keep][:, None]
  
          # pad missing boxes with 0.
          if boxes.shape[0] < proposal_count:
              n_pad_boxes = proposal_count - boxes.shape[0]
              zeros = torch.zeros([n_pad_boxes, boxes.shape[1]]).cuda()
              boxes = torch.cat([boxes, zeros], dim=0)
              zeros = torch.zeros(
                  [n_pad_boxes, rpn_scores.shape[1]]
              ).cuda()
              rpn_scores = torch.cat([rpn_scores, zeros], dim=0)
  
          # concat box and score info for monitoring/plotting.
          batch_out_proposals.append(
              torch.cat((boxes, rpn_scores), 1).cpu().data.numpy()
          )
          # normalize dimensions to range of 0 to 1.
          normalized_boxes = boxes / norm
          # add back batch dimension
          batch_normalized_boxes.append(normalized_boxes.unsqueeze(0))
  
      batch_normalized_boxes = torch.cat(batch_normalized_boxes)
      batch_out_proposals = np.array(batch_out_proposals)
      return batch_normalized_boxes, batch_out_proposals
  
imports: import utils.model_utils
  import utils.exp_utils
  from cuda_functions.nms_2D.pth_nms import nms_gpu
  from cuda_functions.nms_3D.pth_nms import nms_gpu
  from cuda_functions.roi_align_2D.roi_align.crop_and_resize import CropAndResizeFunction
  from cuda_functions.roi_align_3D.roi_align.crop_and_resize import CropAndResizeFunction
  import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  import torch.utils
label_desc: Use image node_id 6 for calling a global function with example usage: proposal_layer(rpn_pred_probs, rpn_pred_deltas, proposal_count, anchors, cf) and returns: batch_normalized_boxes,  batch_out_proposals