class_docstr: Implement the pixel defence approach. Defense based on PixelCNN that projects samples back to the data manifold.
  
  | Paper link: https://arxiv.org/abs/1710.10766
  
  | Please keep in mind the limitations of defences. For more information on the limitations of this defence,
      see https://arxiv.org/abs/1802.00420 . For details on how to evaluate classifier security in general, see
      https://arxiv.org/abs/1902.06705
docstr: Apply pixel defence to sample `x`.
  
  :param x: Sample to defense with shape `(batch_size, width, height, depth)`. `x` values are expected to be in
          the data range [0, 1].
  :param y: Labels of the sample `x`. This function does not affect them in any way.
  :return: Purified sample.
code: def __call__(
      self, x: np.ndarray, y: Optional[np.ndarray] = None
  ) -> Tuple[np.ndarray, Optional[np.ndarray]]:
      """
      Apply pixel defence to sample `x`.
  
      :param x: Sample to defense with shape `(batch_size, width, height, depth)`. `x` values are expected to be in
              the data range [0, 1].
      :param y: Labels of the sample `x`. This function does not affect them in any way.
      :return: Purified sample.
      """
      # Convert into `uint8`
      original_shape = x.shape
      if self.pixel_cnn is not None:
          activations = self.pixel_cnn.get_activations(
              x, layer=-1, batch_size=self.batch_size
          )
          if isinstance(activations, np.ndarray):
              probs = activations.reshape((x.shape[0], -1, 256))
          else:
              raise ValueError("Activations are None.")
      else:
          raise ValueError("No model received for `pixel_cnn`.")
  
      x = x * 255
      x = x.astype("uint8")
      x = x.reshape((x.shape[0], -1))
  
      # Start defence one image at a time
      for i, x_i in enumerate(
          tqdm(x, desc="PixelDefend", disable=not self.verbose)
      ):
          for feat_index in range(x.shape[1]):
              # Setup the search space
              f_probs = probs[i, feat_index, :]
              f_range = range(
                  int(max(x_i[feat_index] - self.eps, 0)),
                  int(min(x_i[feat_index] + self.eps, 255) + 1),
              )
  
              # Look in the search space
              best_prob = -1
              best_idx = -1
              for idx in f_range:
                  if f_probs[idx] > best_prob:
                      best_prob = f_probs[idx]
                      best_idx = idx
  
              # Update result
              x_i[feat_index] = best_idx
  
          # Update in batch
          x[i] = x_i
  
      # Convert to old dtype
      x = x / 255.0
      x = x.astype(ART_NUMPY_DTYPE).reshape(original_shape)
  
      # Clip to clip_values
      x = np.clip(x, self.clip_values[0], self.clip_values[1])
  
      return x, y
  
file_path: adversarial-robustness-toolbox/art/defences/preprocessor/pixel_defend.py
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  from typing import Optional, Tuple, TYPE_CHECKING
  import numpy
  from tqdm.auto import tqdm
  from art.config import ART_NUMPY_DTYPE
  from art.defences.preprocessor.preprocessor import Preprocessor
label_desc: Use image node_id 2 for calling the PixelDefend obj's underlying member method code with example usage: obj.__call__(x, y) and returns: x,  y