# Path: reservoir_nn/typing/types.py

# 
# Path: reservoir_nn/utils/preprocessing.py
# AUTOTUNE = tf.data.experimental.AUTOTUNE
# class DatasetTransform(abc.ABC):
# class TensorTransform(abc.ABC):
# class Sequential(DatasetTransform, list):
# class MapLayer(DatasetTransform, list):
# class ParseDataLayer(DatasetTransform):
# class BatchLayer(DatasetTransform):
# class UnBatchLayer(DatasetTransform):
# class CacheLayer(DatasetTransform):
# class RejectionResampleLayer(DatasetTransform):
# class Identity(TensorTransform):
# class Chain(TensorTransform, list):
# class Lambda(TensorTransform):
# class OneHotLabel(TensorTransform):
# class DemeanTensor(TensorTransform):
# class NormalizeTensor(TensorTransform):
# class Reshape(TensorTransform):
#   def __call__(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
#   def call(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
#   def __call__(self, input_: types.TensorLike) -> tf.Tensor:
#   def call(self, input_: tf.Tensor) -> tf.Tensor:
#   def __init__(self, layers: Optional[Sequence[DatasetTransform]] = None):
#   def __repr__(self):
#   def call(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
#   def __init__(self,
#                transformations: Optional[Sequence[TensorTransform]] = None,
#                num_parallel_calls=AUTOTUNE,
#                deterministic: Optional[bool] = None):
#   def __repr__(self):
#   def map_func(self, *args):
#   def call(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
#   def __init__(self,
#                parser: Callable[..., Union[Tuple[tf.Tensor, ...], tf.Tensor,
#                                            tf.data.Dataset]],
#                flat_map: bool = False,
#                num_parallel_calls=AUTOTUNE,
#                deterministic: Optional[bool] = None):
#   def __repr__(self):
#   def call(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
#   def call(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
#   def call(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
#   def call(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
#   def _get_class_label(self, *args):
#   def call(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
#   def call(self, input_: tf.Tensor) -> tf.Tensor:
#   def __init__(self,
#                transformations: Optional[Sequence[TensorTransform]] = None):
#   def __repr__(self):
#   def call(self, input_: tf.Tensor) -> tf.Tensor:
#   def __init__(self, function: Callable[[tf.Tensor], tf.Tensor]):
#   def __repr__(self) -> str:
#   def call(self, input_: tf.Tensor) -> tf.Tensor:
#   def call(self, input_: tf.Tensor) -> tf.Tensor:
#   def call(self, input_: tf.Tensor) -> tf.Tensor:
#   def call(self, input_: tf.Tensor) -> tf.Tensor:
#   def call(self, input_: tf.Tensor) -> tf.Tensor:


from typing import Tuple
from absl import logging
from reservoir_nn.typing import types
from reservoir_nn.utils import preprocessing
from tensorflow_addons import image as tfa_image
import attr
import numpy as np
import tensorflow as tf
    # Classes not included in input are assigned the value of class "unlabeled"
    otherwise = self.all_class_label_values['unlabeled']

    self._lookup_table = tf.lookup.StaticHashTable(
        tf.lookup.KeyValueTensorInitializer(label_tensor, label_tensor),
        otherwise)

  def call(self, input_: tf.Tensor) -> tf.Tensor:
    """Preserves then separates labels in the input data.

    Args:
      input_: The input labels.

    Returns:
      The transformed label data.
    """
    # Remove the color channel dimension if there is only one color
    if input_.shape[-1] == 1:
      input_ = tf.squeeze(input_, axis=-1)

    # Preserve the input classes and assign the unwanted classes to 'unlabeled'
    output = self._lookup_table.lookup(input_)

    # Create one-hot channels for all potential classes
    outputs = tf.one_hot(
        output, depth=len(self.all_class_label_values), dtype=tf.int32)

    return tf.gather(outputs, self._labels, axis=-1)



# Path: reservoir_nn/typing/types.py

# 
# Path: reservoir_nn/utils/preprocessing.py
# AUTOTUNE = tf.data.experimental.AUTOTUNE
# class DatasetTransform(abc.ABC):
# class TensorTransform(abc.ABC):
# class Sequential(DatasetTransform, list):
# class MapLayer(DatasetTransform, list):
# class ParseDataLayer(DatasetTransform):
# class BatchLayer(DatasetTransform):
# class UnBatchLayer(DatasetTransform):
# class CacheLayer(DatasetTransform):
# class RejectionResampleLayer(DatasetTransform):
# class Identity(TensorTransform):
# class Chain(TensorTransform, list):
# class Lambda(TensorTransform):
# class OneHotLabel(TensorTransform):
# class DemeanTensor(TensorTransform):
# class NormalizeTensor(TensorTransform):
# class Reshape(TensorTransform):
#   def __call__(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
#   def call(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
#   def __call__(self, input_: types.TensorLike) -> tf.Tensor:
#   def call(self, input_: tf.Tensor) -> tf.Tensor:
#   def __init__(self, layers: Optional[Sequence[DatasetTransform]] = None):
#   def __repr__(self):
#   def call(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
#   def __init__(self,
#                transformations: Optional[Sequence[TensorTransform]] = None,
#                num_parallel_calls=AUTOTUNE,
#                deterministic: Optional[bool] = None):
#   def __repr__(self):
#   def map_func(self, *args):
#   def call(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
#   def __init__(self,
#                parser: Callable[..., Union[Tuple[tf.Tensor, ...], tf.Tensor,
#                                            tf.data.Dataset]],
#                flat_map: bool = False,
#                num_parallel_calls=AUTOTUNE,
#                deterministic: Optional[bool] = None):
#   def __repr__(self):
#   def call(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
#   def call(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
#   def call(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
#   def call(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
#   def _get_class_label(self, *args):
#   def call(self, dataset: tf.data.Dataset) -> tf.data.Dataset:
#   def call(self, input_: tf.Tensor) -> tf.Tensor:
#   def __init__(self,
#                transformations: Optional[Sequence[TensorTransform]] = None):
#   def __repr__(self):
#   def call(self, input_: tf.Tensor) -> tf.Tensor:
#   def __init__(self, function: Callable[[tf.Tensor], tf.Tensor]):
#   def __repr__(self) -> str:
#   def call(self, input_: tf.Tensor) -> tf.Tensor:
#   def call(self, input_: tf.Tensor) -> tf.Tensor:
#   def call(self, input_: tf.Tensor) -> tf.Tensor:
#   def call(self, input_: tf.Tensor) -> tf.Tensor:
#   def call(self, input_: tf.Tensor) -> tf.Tensor:


# Path: reservoir_nn/utils/image_operations.py
from typing import Tuple
from absl import logging
from reservoir_nn.typing import types
from reservoir_nn.utils import preprocessing
from tensorflow_addons import image as tfa_image
import attr
import numpy as np
import tensorflow as tf

    # Classes not included in input are assigned the value of class "unlabeled"
    otherwise = self.all_class_label_values['unlabeled']

    self._lookup_table = tf.lookup.StaticHashTable(
        tf.lookup.KeyValueTensorInitializer(label_tensor, label_tensor),
        otherwise)

  def call(self, input_: tf.Tensor) -> tf.Tensor:
    """Preserves then separates labels in the input data.

    Args:
      input_: The input labels.

    Returns:
      The transformed label data.
    """
    # Remove the color channel dimension if there is only one color
    if input_.shape[-1] == 1:
      input_ = tf.squeeze(input_, axis=-1)

    # Preserve the input classes and assign the unwanted classes to 'unlabeled'
    output = self._lookup_table.lookup(input_)

    # Create one-hot channels for all potential classes
    outputs = tf.one_hot(
        output, depth=len(self.all_class_label_values), dtype=tf.int32)

    return tf.gather(outputs, self._labels, axis=-1)



def merge_labels(label: types.TensorLike) -> tf.Tensor: