class_docstr: TensorMask model. Creates FPN backbone, anchors and a head for classification
  and box regression. Calculates and applies proper losses to class, box, and
  masks.
docstr: Args:
      anchors (list[list[Boxes]]): a list of N=#image elements. Each is a
          list of #feature level Boxes. The Boxes contains anchors of
          this image on the specific feature level.
      unit_lengths (list[list[Tensor]]): a list of N=#image elements. Each is a
          list of #feature level Tensor. The tensor contains unit lengths for anchors of
          this image on the specific feature level.
      indexes (list[list[Tensor]]): a list of N=#image elements. Each is a
          list of #feature level Tensor. The tensor contains the 5D index of
          each anchor, the second dimension means (L, N, H, W, A), where L
          is level, I is image, H is height, W is width, and A is anchor.
      targets (list[Instances]): a list of N `Instances`s. The i-th
          `Instances` contains the ground-truth per-instance annotations
          for the i-th input image.  Specify `targets` during training only.
  
  Returns:
      gt_class_info (Tensor, Tensor): A pair of two tensors for classification.
          The first one is an integer tensor of shape (R, #classes) storing ground-truth
          labels for each anchor. R is the total number of anchors in the batch.
          The second one is an integer tensor of shape (R,), to indicate which
          anchors are valid for loss computation, which anchors are not.
      gt_delta_info (Tensor, Tensor): A pair of two tensors for boxes.
          The first one, of shape (F, 4). F=#foreground anchors.
          The last dimension represents ground-truth box2box transform
          targets (dx, dy, dw, dh) that map each anchor to its matched ground-truth box.
          Only foreground anchors have values in this tensor. Could be `None` if F=0.
          The second one, of shape (R,), is an integer tensor indicating which anchors
          are foreground ones used for box regression. Could be `None` if F=0.
      gt_mask_info (list[list[Tensor]], list[list[Tensor]]): A pair of two lists for masks.
          The first one is a list of P=#feature level elements. Each is a
          list of A=#anchor tensors. Each tensor contains the ground truth
          masks of the same size and for the same feature level. Could be `None`.
          The second one is a list of P=#feature level elements. Each is a
          list of A=#anchor tensors. Each tensor contains the location of the ground truth
          masks of the same size and for the same feature level. The second dimension means
          (N, H, W), where N is image, H is height, and W is width. Could be `None`.
      num_fg (int): F=#foreground anchors, used later for loss normalization.
docstr_tok: ["Args",":","anchors","(","list","[","list","[","Boxes","]","]",")",":","a","list","of","N=","#","image","elements",".","Each","is","a","list","of","#","feature","level","Boxes",".","The","Boxes","contains","anchors","of","this","image","on","the","specific","feature","level",".","unit_lengths","(","list","[","list","[","Tensor","]","]",")",":","a","list","of","N=","#","image","elements",".","Each","is","a","list","of","#","feature","level","Tensor",".","The","tensor","contains","unit","lengths","for","anchors","of","this","image","on","the","specific","feature","level",".","indexes","(","list","[","list","[","Tensor","]","]",")",":","a","list","of","N=","#","image","elements",".","Each","is","a","list","of","#","feature","level","Tensor",".","The","tensor","contains","the","5D","index","of","each","anchor",",","the","second","dimension","means","(","L",",","N",",","H",",","W",",","A",")",",","where","L","is","level",",","I","is","image",",","H","is","height",",","W","is","width",",","and","A","is","anchor",".","targets","(","list","[","Instances","]",")",":","a","list","of","N","`","Instances","`","s",".","The","i-th","`","Instances","`","contains","the","ground-truth","per-instance","annotations","for","the","i-th","input","image",".","Specify","`","targets","`","during","training","only",".","Returns",":","gt_class_info","(","Tensor",",","Tensor",")",":","A","pair","of","two","tensors","for","classification",".","The","first","one","is","an","integer","tensor","of","shape","(","R",",","#","classes",")","storing","ground-truth","labels","for","each","anchor",".","R","is","the","total","number","of","anchors","in","the","batch",".","The","second","one","is","an","integer","tensor","of","shape","(","R",",",")",",","to","indicate","which","anchors","are","valid","for","loss","computation",",","which","anchors","are","not",".","gt_delta_info","(","Tensor",",","Tensor",")",":","A","pair","of","two","tensors","for","boxes",".","The","first","one",",","of","shape","(","F",",","4",")",".","F=","#","foreground","anchors",".","The","last","dimension","represents","ground-truth","box2box","transform","targets","(","dx",",","dy",",","dw",",","dh",")","that","map","each","anchor","to","its","matched","ground-truth","box",".","Only","foreground","anchors","have","values","in","this","tensor",".","Could","be","`","None","`","if","F=0",".","The","second","one",",","of","shape","(","R",",",")",",","is","an","integer","tensor","indicating","which","anchors","are","foreground","ones","used","for","box","regression",".","Could","be","`","None","`","if","F=0",".","gt_mask_info","(","list","[","list","[","Tensor","]","]",",","list","[","list","[","Tensor","]","]",")",":","A","pair","of","two","lists","for","masks",".","The","first","one","is","a","list","of","P=","#","feature","level","elements",".","Each","is","a","list","of","A=","#","anchor","tensors",".","Each","tensor","contains","the","ground","truth","masks","of","the","same","size","and","for","the","same","feature","level",".","Could","be","`","None","`",".","The","second","one","is","a","list","of","P=","#","feature","level","elements",".","Each","is","a","list","of","A=","#","anchor","tensors",".","Each","tensor","contains","the","location","of","the","ground","truth","masks","of","the","same","size","and","for","the","same","feature","level",".","The","second","dimension","means","(","N",",","H",",","W",")",",","where","N","is","image",",","H","is","height",",","and","W","is","width",".","Could","be","`","None","`",".","num_fg","(","int",")",":","F=","#","foreground","anchors",",","used","later","for","loss","normalization","."]
code: def get_ground_truth(self, anchors, unit_lengths, indexes, targets):
      """
      Args:
          anchors (list[list[Boxes]]): a list of N=#image elements. Each is a
              list of #feature level Boxes. The Boxes contains anchors of
              this image on the specific feature level.
          unit_lengths (list[list[Tensor]]): a list of N=#image elements. Each is a
              list of #feature level Tensor. The tensor contains unit lengths for anchors of
              this image on the specific feature level.
          indexes (list[list[Tensor]]): a list of N=#image elements. Each is a
              list of #feature level Tensor. The tensor contains the 5D index of
              each anchor, the second dimension means (L, N, H, W, A), where L
              is level, I is image, H is height, W is width, and A is anchor.
          targets (list[Instances]): a list of N `Instances`s. The i-th
              `Instances` contains the ground-truth per-instance annotations
              for the i-th input image.  Specify `targets` during training only.
  
      Returns:
          gt_class_info (Tensor, Tensor): A pair of two tensors for classification.
              The first one is an integer tensor of shape (R, #classes) storing ground-truth
              labels for each anchor. R is the total number of anchors in the batch.
              The second one is an integer tensor of shape (R,), to indicate which
              anchors are valid for loss computation, which anchors are not.
          gt_delta_info (Tensor, Tensor): A pair of two tensors for boxes.
              The first one, of shape (F, 4). F=#foreground anchors.
              The last dimension represents ground-truth box2box transform
              targets (dx, dy, dw, dh) that map each anchor to its matched ground-truth box.
              Only foreground anchors have values in this tensor. Could be `None` if F=0.
              The second one, of shape (R,), is an integer tensor indicating which anchors
              are foreground ones used for box regression. Could be `None` if F=0.
          gt_mask_info (list[list[Tensor]], list[list[Tensor]]): A pair of two lists for masks.
              The first one is a list of P=#feature level elements. Each is a
              list of A=#anchor tensors. Each tensor contains the ground truth
              masks of the same size and for the same feature level. Could be `None`.
              The second one is a list of P=#feature level elements. Each is a
              list of A=#anchor tensors. Each tensor contains the location of the ground truth
              masks of the same size and for the same feature level. The second dimension means
              (N, H, W), where N is image, H is height, and W is width. Could be `None`.
          num_fg (int): F=#foreground anchors, used later for loss normalization.
      """
      gt_classes = []
      gt_deltas = []
      gt_masks = [
          [[] for _ in range(self.num_anchors)]
          for _ in range(self.num_levels)
      ]
      gt_mask_inds = [
          [[] for _ in range(self.num_anchors)]
          for _ in range(self.num_levels)
      ]
  
      anchors = [Boxes.cat(anchors_i) for anchors_i in anchors]
      unit_lengths = [
          cat(unit_lengths_i) for unit_lengths_i in unit_lengths
      ]
      indexes = [cat(indexes_i) for indexes_i in indexes]
  
      num_fg = 0
      for i, (
          anchors_im,
          unit_lengths_im,
          indexes_im,
          targets_im,
      ) in enumerate(zip(anchors, unit_lengths, indexes, targets)):
          # Initialize all
          gt_classes_i = torch.full_like(
              unit_lengths_im,
              self.num_classes,
              dtype=torch.int64,
              device=self.device,
          )
          # Ground truth classes
          has_gt = len(targets_im) > 0
          if has_gt:
              # Compute the pairwise matrix
              gt_matched_inds, anchor_labels = _assignment_rule(
                  targets_im.gt_boxes,
                  anchors_im,
                  unit_lengths_im,
                  self.min_anchor_size,
              )
              # Find the foreground instances
              fg_inds = anchor_labels == 1
              fg_anchors = anchors_im[fg_inds]
              num_fg += len(fg_anchors)
              # Find the ground truths for foreground instances
              gt_fg_matched_inds = gt_matched_inds[fg_inds]
              # Assign labels for foreground instances
              gt_classes_i[fg_inds] = targets_im.gt_classes[
                  gt_fg_matched_inds
              ]
              # Anchors with label -1 are ignored, others are left as negative
              gt_classes_i[anchor_labels == -1] = -1
  
              # Boxes
              # Ground truth box regression, only for foregrounds
              matched_gt_boxes = targets_im[gt_fg_matched_inds].gt_boxes
              # Compute box regression offsets for foregrounds only
              gt_deltas_i = self.box2box_transform.get_deltas(
                  fg_anchors.tensor, matched_gt_boxes.tensor
              )
              gt_deltas.append(gt_deltas_i)
  
              # Masks
              if self.mask_on:
                  # Compute masks for each level and each anchor
                  matched_indexes = indexes_im[fg_inds, :]
                  for lvl in range(self.num_levels):
                      ids_lvl = matched_indexes[:, 0] == lvl
                      if torch.any(ids_lvl):
                          cur_level_factor = (
                              2**lvl if self.bipyramid_on else 1
                          )
                          for anc in range(self.num_anchors):
                              ids_lvl_anchor = ids_lvl & (
                                  matched_indexes[:, 4] == anc
                              )
                              if torch.any(ids_lvl_anchor):
                                  gt_masks[lvl][anc].append(
                                      targets_im[
                                          gt_fg_matched_inds[
                                              ids_lvl_anchor
                                          ]
                                      ].gt_masks.crop_and_resize(
                                          fg_anchors[
                                              ids_lvl_anchor
                                          ].tensor,
                                          self.mask_sizes[anc]
                                          * cur_level_factor,
                                      )
                                  )
                                  # Select (N, H, W) dimensions
                                  gt_mask_inds_lvl_anc = (
                                      matched_indexes[
                                          ids_lvl_anchor, 1:4
                                      ]
                                  )
                                  # Set the image index to the current image
                                  gt_mask_inds_lvl_anc[:, 0] = i
                                  gt_mask_inds[lvl][anc].append(
                                      gt_mask_inds_lvl_anc
                                  )
          gt_classes.append(gt_classes_i)
  
      # Classes and boxes
      gt_classes = cat(gt_classes)
      gt_valid_inds = gt_classes >= 0
      gt_fg_inds = gt_valid_inds & (gt_classes < self.num_classes)
      gt_classes_target = torch.zeros(
          (gt_classes.shape[0], self.num_classes),
          dtype=torch.float32,
          device=self.device,
      )
      gt_classes_target[gt_fg_inds, gt_classes[gt_fg_inds]] = 1
      gt_deltas = cat(gt_deltas) if gt_deltas else None
  
      # Masks
      gt_masks = [
          [cat(mla) if mla else None for mla in ml] for ml in gt_masks
      ]
      gt_mask_inds = [
          [cat(ila) if ila else None for ila in il]
          for il in gt_mask_inds
      ]
      return (
          (gt_classes_target, gt_valid_inds),
          (gt_deltas, gt_fg_inds),
          (gt_masks, gt_mask_inds),
          num_fg,
      )
  
imports: import copy
  import math
  from typing import List
  import torch
  import torch.nn.functional
  from fvcore.nn import sigmoid_focal_loss_star_jit, smooth_l1_loss
  from torch import nn
  from detectron2.layers import ShapeSpec, batched_nms, cat, paste_masks_in_image
  from detectron2.modeling.anchor_generator import DefaultAnchorGenerator
  from detectron2.modeling.backbone import build_backbone
  from detectron2.modeling.box_regression import Box2BoxTransform
  from detectron2.modeling.meta_arch.build import META_ARCH_REGISTRY
  from detectron2.modeling.meta_arch.retinanet import permute_to_N_HWA_K
  from detectron2.structures import Boxes, ImageList, Instances
  from tensormask.layers import SwapAlign2Nat
label_desc: Use image node_id 5 for calling the TensorMask obj's underlying member method code with example usage: obj.get_ground_truth(anchors, unit_lengths, indexes, targets) and returns: gt_classes_target,  gt_valid_inds,  gt_deltas,  gt_fg_inds,  gt_masks,  gt_mask_inds,  num_fg