code: def mosaic_creation(
      images: np.ndarray,
      labels: np.ndarray,
      mosaics_per_class: int,
      seed: Optional[int] = None,
  ) -> Tuple[
      Any,
      List[Tuple[Any, ...]],
      List[Tuple[Any, ...]],
      List[Tuple[int, ...]],
      List[Any],
  ]:
      """
      Build a mosaic dataset from an image dataset (images). Each mosaic corresponds to a 2x2 grid. Each one
      is composed by four images: two belonging to the target class and the other two are chosen randomly from
      the rest of the classes.
  
      Parameters
      ----------
      images: np.ndarray
           A np.ndarray which contains the input data.
      labels: np.ndarray
           A np.ndarray which contains the labels from the input data.
      mosaics_per_class: integer
          An integer indicating the number of mosaics per class.
      seed: integer
          An integer used to generate a random number (optional)..
  
      Returns
      -------
      all_mosaics: np.ndarray
           a np.ndarray which contains the mosaic data
      mosaic_indices_list: a List[Tuple[int, int, int, int]] which contains the image indices corresponding to the images
                           composing each mosaic
      mosaic_labels_list (List[Tuple[Union[int, str], ...]]): a List[Tuple[Union[int, str], ...]] which contains the labels of the images composing each
                          mosaic. Each tuple contains four values referring to (top_left_label, top_right_label,
                          bottom_left_label, bottom_right_label)
      p_batch_list (List[Tuple[int, int, int, int]]): a List[Tuple[int, int, int, int]] which contains the positions of the target class within the mosaic.
                    Each tuple contains 0 and 1 values (non_target_class and target_class) referring to (top_left, top_right, bottom_left, bottom_right).
      target_list (List[Union[int, str]]): a List[Union[int, str]] which contains the target class of each mosaic.
      """
  
      args = []
      if seed:
          args = [seed]
      rng = random.Random(*args)
  
      mosaics_images_list = []
      mosaic_indices_list = []
      mosaic_labels_list = []
      p_batch_list = []
      target_list = []
      total_labels = list(np.unique(labels))
  
      for target_class in total_labels:
          outer_classes = total_labels.copy()
          outer_classes.remove(target_class)
  
          target_class_images = images[labels == target_class]
          target_class_image_indices = np.where(labels == target_class)[
              0
          ]
          target_class_images_and_indices = list(
              zip(target_class_images, target_class_image_indices)
          )
  
          no_repetitions = int(
              math.ceil(
                  (2 * mosaics_per_class) / len(target_class_images)
              )
          )
          total_target_class_images_and_indices = (
              target_class_images_and_indices * no_repetitions
          )
          rng.shuffle(total_target_class_images_and_indices)
  
          no_outer_images_per_class = int(
              math.ceil((2 * mosaics_per_class) / len(outer_classes))
          )
          total_outer_images_and_indices = []
          total_outer_labels = []
          for outer_class in outer_classes:
              outer_class_images = images[labels == outer_class]
              outer_class_images_indices = np.where(
                  labels == outer_class
              )[0]
              outer_class_images_and_indices = list(
                  zip(outer_class_images, outer_class_images_indices)
              )
  
              current_outer_images_and_indices = rng.choices(
                  outer_class_images_and_indices,
                  k=no_outer_images_per_class,
              )
              total_outer_images_and_indices += (
                  current_outer_images_and_indices
              )
              total_outer_labels += [
                  outer_class
              ] * no_outer_images_per_class
  
          total_outer = list(
              zip(total_outer_images_and_indices, total_outer_labels)
          )
          rng.shuffle(total_outer)
  
          iter_images_and_indices = iter(
              total_target_class_images_and_indices
          )
          iter_outer = iter(total_outer)
          for _ in range(mosaics_per_class):
              mosaic_elems = [
                  (next(iter_images_and_indices), target_class),
                  (next(iter_images_and_indices), target_class),
                  next(iter_outer),
                  next(iter_outer),
              ]
              rng.shuffle(mosaic_elems)
  
              current_mosaic = build_single_mosaic(
                  [elem[0][0] for elem in mosaic_elems]
              )
              mosaics_images_list.append(current_mosaic)
  
              mosaic_indices = tuple(
                  elem[0][1] for elem in mosaic_elems
              )
              mosaic_indices_list.append(mosaic_indices)
  
              current_targets = tuple(elem[1] for elem in mosaic_elems)
              mosaic_labels_list.append(current_targets)
  
              current_p_batch = tuple(
                  int(elem[1] == target_class) for elem in mosaic_elems
              )
              p_batch_list.append(current_p_batch)
  
              target_list.append(target_class)
  
      all_mosaics = np.array(mosaics_images_list)
  
      return (
          all_mosaics,
          mosaic_indices_list,
          mosaic_labels_list,
          p_batch_list,
          target_list,
      )
  
imports: import math
  import random
  from typing import List, Tuple, Optional, Union, Any
  import numpy
label_desc: Use image node_id 2 for calling a global function with example usage: mosaic_creation(images, labels, mosaics_per_class, seed) and returns: all_mosaics,  mosaic_indices_list,  mosaic_labels_list,  p_batch_list,  target_list