# Path: init2winit/dataset_lib/data_utils.py
# def iterator_as_numpy(iterator):
# def image_iterator(data,
#                    rescale,
#                    output_shape,
#                    is_one_hot,
#                    autoencoder,
#                    shuffle_rng=None,
#                    augment_fn=None,
#                    include_example_keys=False):
# def maybe_pad_batch(batch,
#                     desired_batch_size,
#                     data_format=None,
#                     mask_key=None):
#   def zero_pad(ar, pad_axis):
# def shard(batch, n_devices=None):
#   def _shard_array(array):
# def tf_to_numpy(tfds_data):
# 
# Path: init2winit/dataset_lib/image_preprocessing.py
# def _crop(key, image, hps):
# def crop(key, images, hps):
# def mixup_general(key,
#                   *args_to_mix,
#                   alpha=0.1,
#                   fold_in=None,
#                   n=2,
#                   **kwargs_to_mix):
#   def mix(batch):
#     def mul(a, b):  # B * BHWC -> B111 * BHWC
# def mixup(key, alpha, images, labels):
# def augment_cifar10(key, images, labels, hps):
# def identity_augment(key, images, labels):
# 
# Path: init2winit/dataset_lib/data_utils.py
# def iterator_as_numpy(iterator):
# def image_iterator(data,
#                    rescale,
#                    output_shape,
#                    is_one_hot,
#                    autoencoder,
#                    shuffle_rng=None,
#                    augment_fn=None,
#                    include_example_keys=False):
# def maybe_pad_batch(batch,
#                     desired_batch_size,
#                     data_format=None,
#                     mask_key=None):
#   def zero_pad(ar, pad_axis):
# def shard(batch, n_devices=None):
#   def _shard_array(array):
# def tf_to_numpy(tfds_data):


import functools
import itertools
import jax.numpy as jnp
import jax.random
import numpy as np
import tensorflow.compat.v2 as tf
import tensorflow_datasets as tfds
from absl import logging
from init2winit.dataset_lib import data_utils
from init2winit.dataset_lib import image_preprocessing
from init2winit.dataset_lib.data_utils import Dataset
from ml_collections.config_dict import config_dict
  a data generator is:
    for batch in train_gen(epoch):
       ...
  suffle_rng is used with the epoch number to shuffle the train epoch every
  epoch. We do not shuffle the validation or test sets. We load the entire
  dataset into memory (60000 images). The last batch may be smaller than
  batch_size if batch_size does not evenly divide the size of the data. The
  validation set is chosen to be the last 10000 images of the tfds train set.
  Note this has already been shuffled, so this will not necessarily correspond
  to any particular validation set.

  Args:
    shuffle_rng: jax.random.PRNGKey
    batch_size: The global train batch size, used to determine the batch size
      yielded from train_epoch().
    eval_batch_size: The global eval batch size, used to determine the batch
      size yielded from valid_epoch() and test_epoch().
    hps: Hparams object. hps.train_size, hps.valid_size, and hps.test_size will
      specify the sizes of the various data splits. See image_preprocessing for
      hparams that control the data augmentation.
  Returns:
    train_epoch, valid_epoch, test_epoch: three generators.
  """
  per_host_batch_size = batch_size // jax.process_count()
  per_host_eval_batch_size = eval_batch_size // jax.process_count()

  mean = jnp.array([129.3041658, 124.06996185, 112.4340492])[None, None,
                                                             None, :]
  std = jnp.array([68.17024395, 65.3918073, 70.41836985])[None, None, None, :]
  rescale = lambda x: (x - mean) / std

# Path: init2winit/dataset_lib/data_utils.py
# def iterator_as_numpy(iterator):
# def image_iterator(data,
#                    rescale,
#                    output_shape,
#                    is_one_hot,
#                    autoencoder,
#                    shuffle_rng=None,
#                    augment_fn=None,
#                    include_example_keys=False):
# def maybe_pad_batch(batch,
#                     desired_batch_size,
#                     data_format=None,
#                     mask_key=None):
#   def zero_pad(ar, pad_axis):
# def shard(batch, n_devices=None):
#   def _shard_array(array):
# def tf_to_numpy(tfds_data):
# 
# Path: init2winit/dataset_lib/image_preprocessing.py
# def _crop(key, image, hps):
# def crop(key, images, hps):
# def mixup_general(key,
#                   *args_to_mix,
#                   alpha=0.1,
#                   fold_in=None,
#                   n=2,
#                   **kwargs_to_mix):
#   def mix(batch):
#     def mul(a, b):  # B * BHWC -> B111 * BHWC
# def mixup(key, alpha, images, labels):
# def augment_cifar10(key, images, labels, hps):
# def identity_augment(key, images, labels):
# 
# Path: init2winit/dataset_lib/data_utils.py
# def iterator_as_numpy(iterator):
# def image_iterator(data,
#                    rescale,
#                    output_shape,
#                    is_one_hot,
#                    autoencoder,
#                    shuffle_rng=None,
#                    augment_fn=None,
#                    include_example_keys=False):
# def maybe_pad_batch(batch,
#                     desired_batch_size,
#                     data_format=None,
#                     mask_key=None):
#   def zero_pad(ar, pad_axis):
# def shard(batch, n_devices=None):
#   def _shard_array(array):
# def tf_to_numpy(tfds_data):


# Path: init2winit/dataset_lib/small_image_datasets.py
import functools
import itertools
import jax.numpy as jnp
import jax.random
import numpy as np
import tensorflow.compat.v2 as tf
import tensorflow_datasets as tfds
from absl import logging
from init2winit.dataset_lib import data_utils
from init2winit.dataset_lib import image_preprocessing
from init2winit.dataset_lib.data_utils import Dataset
from ml_collections.config_dict import config_dict

  a data generator is:
    for batch in train_gen(epoch):
       ...
  suffle_rng is used with the epoch number to shuffle the train epoch every
  epoch. We do not shuffle the validation or test sets. We load the entire
  dataset into memory (60000 images). The last batch may be smaller than
  batch_size if batch_size does not evenly divide the size of the data. The
  validation set is chosen to be the last 10000 images of the tfds train set.
  Note this has already been shuffled, so this will not necessarily correspond
  to any particular validation set.

  Args:
    shuffle_rng: jax.random.PRNGKey
    batch_size: The global train batch size, used to determine the batch size
      yielded from train_epoch().
    eval_batch_size: The global eval batch size, used to determine the batch
      size yielded from valid_epoch() and test_epoch().
    hps: Hparams object. hps.train_size, hps.valid_size, and hps.test_size will
      specify the sizes of the various data splits. See image_preprocessing for
      hparams that control the data augmentation.
  Returns:
    train_epoch, valid_epoch, test_epoch: three generators.
  """
  per_host_batch_size = batch_size // jax.process_count()
  per_host_eval_batch_size = eval_batch_size // jax.process_count()

  mean = jnp.array([129.3041658, 124.06996185, 112.4340492])[None, None,
                                                             None, :]
  std = jnp.array([68.17024395, 65.3918073, 70.41836985])[None, None, None, :]
  rescale = lambda x: (x - mean) / std

  augment_fn = functools.partial(image_preprocessing.augment_cifar10, hps=hps)