class_docstr: This class is a wrapper for iterating over datasets for multiple or similar tasks, typically useful for
  multi-task training.
  `task_name` and `sampler_config` are two mandatory keys that allows us to use task-specific data samplers.
  For specifying batch sizes, we use `train_batch_size0`, and `val_batch_size0` as keys for
  training and validation sets. Note that the batch sizes are scaled automatically depending on the number of GPUs.
  
  Args:
      opts: Command-line arguments
      data_samplers: dictionary containing different samplers
  
  Example::
  # Example yaml config for combining different samplers is given below.
  # Please note that configuration for each sampler should start with `-` in `chain_sampler`.
  
  sampler:
      name: "chain_sampler"
      chain_sampler_mode: "sequential"
      chain_sampler:
        - task_name: "segmentation"
          train_batch_size0: 10
          sampler_config:
            name: "variable_batch_sampler"
            use_shards: false
            num_repeats: 4
            truncated_repeat_aug_sampler: false
            vbs:
              crop_size_width: 512
              crop_size_height: 512
              max_n_scales: 25
              min_crop_size_width: 256
              max_crop_size_width: 768
              min_crop_size_height: 256
              max_crop_size_height: 768
              check_scale: 16
        - task_name: "classification"
          train_batch_size0: 20
          sampler_config:
            name: "batch_sampler"
            bs:
              crop_size_width: 512
              crop_size_height: 512
code: def __init__(
      self,
      opts: argparse.Namespace,
      *args,
      **kwargs,
  ) -> None:
      data_samplers = ChainSampler.build_chain_sampler(
          opts, *args, **kwargs
      )
      sampling_mode = getattr(opts, "sampler.chain_sampler_mode")
  
      if sampling_mode is None:
          logger.error(
              f"Sampling mode can't be None in {self.__class__.__name__}"
          )
      if not isinstance(sampling_mode, str):
          logger.error(
              f"Sampling mode in {self.__class__.__name__} should be a type of string. Got: {type(sampling_mode)}"
          )
  
      if sampling_mode not in self._SUPPORTED_SAMPLING_MODES:
          logger.error(
              f"Supported sampling mode in {self.__class__.__name__} are {self._SUPPORTED_SAMPLING_MODES}. "
              f"Got: {sampling_mode}"
          )
      self.samplers_dict = data_samplers
      self.sampling_mode = sampling_mode
  
imports: from __future__ import annotations
  import argparse
  import copy
  import itertools
  import json
  from typing import Iterator, List, Mapping, Optional, Tuple
  from torch.utils.data.sampler import Sampler
  from data.sampler import SAMPLER_REGISTRY, build_sampler
  from options.utils import flatten_yaml_as_dict
  from utils import logger
label_desc: Use image node_id 1 to create a new ChainSampler object from inherited base classes: Sampler with example: obj = ChainSampler(opts)