class_docstr: Implementation of the spatial transformation attack using translation and rotation of inputs. The attack conducts
  black-box queries to the target model in a grid search over possible translations and rotations to find optimal
  attack parameters.
  
  | Paper link: https://arxiv.org/abs/1712.02779
code: def _perturb(
      self, x: np.ndarray, trans_x: int, trans_y: int, rot: float
  ) -> np.ndarray:
      if not self.estimator.channels_first:
          x_adv = shift(x, [0, trans_x, trans_y, 0])
          x_adv = rotate(x_adv, angle=rot, axes=(1, 2), reshape=False)
      elif self.estimator.channels_first:
          x_adv = shift(x, [0, 0, trans_x, trans_y])
          x_adv = rotate(x_adv, angle=rot, axes=(2, 3), reshape=False)
      else:
          raise ValueError("Unsupported channel_first value.")
  
      if self.estimator.clip_values is not None:
          np.clip(
              x_adv,
              self.estimator.clip_values[0],
              self.estimator.clip_values[1],
              out=x_adv,
          )
  
      return x_adv
  
file_path: adversarial-robustness-toolbox/art/attacks/evasion/spatial_transformation.py
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import logging
  from typing import Optional, TYPE_CHECKING
  import numpy
  from scipy.ndimage import rotate, shift
  from tqdm.auto import tqdm
  from art.attacks.attack import EvasionAttack
  from art.estimators.estimator import BaseEstimator, NeuralNetworkMixin
label_desc: Use image node_id 3 for calling the SpatialTransformation obj's underlying member method code with example usage: obj._perturb(x, trans_x, trans_y, rot) and returns: x_adv