code: def build_detection_train_loader(cfg, mapper=None):
      """
      A data loader is created by the following steps:
  
      1. Use the dataset names in config to query :class:`DatasetCatalog`, and obtain a list of dicts.
      2. Coordinate a random shuffle order shared among all processes (all GPUs)
      3. Each process spawn another few workers to process the dicts. Each worker will:
         * Map each metadata dict into another format to be consumed by the model.
         * Batch them by simply putting dicts into a list.
  
      The batched ``list[mapped_dict]`` is what this dataloader will yield.
  
      Args:
          cfg (CfgNode): the config
          mapper (callable): a callable which takes a sample (dict) from dataset and
              returns the format to be consumed by the model.
              By default it will be `DatasetMapper.from_config(cfg, True)`.
  
      Returns:
          an infinite iterator of training data
      """
      dataset_dicts = get_detection_dataset_dicts(
          cfg.CONFIG.DATA.DATASET.TRAIN,
          filter_empty=cfg.CONFIG.DATA.DETECTION.FILTER_EMPTY_ANNOTATIONS,
          min_keypoints=cfg.CONFIG.MODEL.ROI_KEYPOINT_HEAD.MIN_KEYPOINTS_PER_IMAGE
          if cfg.CONFIG.DATA.KEYPOINT_ON
          else 0,
          proposal_files=cfg.CONFIG.DATA.DATASET.PROPOSAL_FILES_TRAIN
          if cfg.CONFIG.DATA.LOAD_PROPOSALS
          else None,
      )
      dataset = DatasetFromList(dataset_dicts, copy=False)
  
      if mapper is None:
          mapper = DatasetMapper.from_config(cfg, True)
      dataset = MapDataset(dataset, mapper)
  
      sampler_name = cfg.CONFIG.DATA.DETECTION.SAMPLER_TRAIN
      logger = logging.getLogger(__name__)
      logger.info("Using training sampler {}".format(sampler_name))
      # TODO avoid if-else?
      if sampler_name == "TrainingSampler":
          sampler = TrainingSampler(len(dataset))
      elif sampler_name == "RepeatFactorTrainingSampler":
          repeat_factors = RepeatFactorTrainingSampler.repeat_factors_from_category_frequency(
              dataset_dicts, cfg.CONFIG.DATA.DETECTION.REPEAT_THRESHOLD
          )
          sampler = RepeatFactorTrainingSampler(repeat_factors)
      else:
          raise ValueError(
              "Unknown training sampler: {}".format(sampler_name)
          )
      return build_batch_data_loader(
          dataset,
          sampler,
          cfg.CONFIG.TRAIN.BATCH_SIZE,
          aspect_ratio_grouping=cfg.CONFIG.DATA.DETECTION.ASPECT_RATIO_GROUPING,
          num_workers=cfg.CONFIG.DATA.NUM_WORKERS,
      )
  
imports: import itertools
  import random
  import logging
  import operator
  import dill
  import pickle
  from pprint import pformat
  from typing import List, Optional, Union
  import numpy
  import torch
  import torch.utils.data
  from ..structures import BoxMode
  from ...utils.comm import get_world_size
  from ...utils.random import seed_all_rng
  from ..transforms import instance_transforms
  from ..registry.catalog import DatasetCatalog, MetadataCatalog
  from .detection_utils import check_metadata_consistency
  from .None import detection_utils
  from .samplers import InferenceSampler, RepeatFactorTrainingSampler, TrainingSampler
label_desc: Use image node_id 7 for calling a global function with example usage: build_detection_train_loader(cfg, mapper) and returns: build_batch_data_loader