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
docstr: Assuming we have samples from N datasets, then this function first iterates over
  the entire first dataset, then the entire second dataset, and so on
  
  Example:
      Dataset 1: [A, B, C]
      Dataset 2: [D, E, F, G, H]
  
      The result of this sampler would be something like this [A, B, C, D, E, F, G, H]
docstr_tok: ["Assuming","we","have","samples","from","N","datasets",",","then","this","function","first","iterates","over","the","entire","first","dataset",",","then","the","entire","second","dataset",",","and","so","on","Example",":","Dataset","1",":","[","A",",","B",",","C","]","Dataset","2",":","[","D",",","E",",","F",",","G",",","H","]","The","result","of","this","sampler","would","be","something","like","this","[","A",",","B",",","C",",","D",",","E",",","F",",","G",",","H","]"]
code: def _sequential_sampling(self) -> List[Tuple]:
      """Assuming we have samples from N datasets, then this function first iterates over
      the entire first dataset, then the entire second dataset, and so on
  
      Example:
          Dataset 1: [A, B, C]
          Dataset 2: [D, E, F, G, H]
  
          The result of this sampler would be something like this [A, B, C, D, E, F, G, H]
  
      """
      for task_name, dataset_sampler in self.samplers_dict.items():
          for batch_data in dataset_sampler:
              # append dataset name to the batch data
              yield [x + (task_name,) for x in batch_data]
  
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 4 for calling the ChainSampler obj's underlying member method code with example usage: obj._sequential_sampling() without return types