def get_activations(
        self, x: np.ndarray, layer: int | str, batch_size: int = 128, framework: bool = False
    ) -> np.ndarray:
        """
        Return the output of the specified layer for input `x`. `layer` is specified by layer index (between 0 and
        `nb_layers - 1`) or by name. The number of layers can be determined by counting the results returned by
        calling `layer_names`.

        :param x: Input for computing the activations.
        :param layer: Layer for computing the activations.
        :param batch_size: Size of batches.
        :param framework: If true, return the intermediate tensor representation of the activation.
        :return: The output of `layer`, where the first dimension is the batch size corresponding to `x`.
        """

        import tensorflow.compat.v1 as tf

        if self.learning is not None:
            self.feed_dict[self.learning] = False

        # Get the computational graph
        with self._sess.graph.as_default():
            graph = tf.get_default_graph()

        if isinstance(layer, six.string_types):  # basestring for Python 2 (str, unicode) support
            if layer not in self._layer_names:  # pragma: no cover
                raise ValueError(f"Layer name {layer} is not part of the graph.")
            layer_tensor = graph.get_tensor_by_name(layer)

        elif isinstance(layer, int):
            layer_tensor = graph.get_tensor_by_name(self._layer_names[layer])

        else:  # pragma: no cover
            raise TypeError(f"Layer must be of type `str` or `int`. Received {layer}.")

        if framework:
            return layer_tensor

        # Apply preprocessing
        x_preprocessed, _ = self._apply_preprocessing(x, y=None, fit=False)

        # Run prediction with batch processing
        results = []
        num_batch = int(np.ceil(len(x_preprocessed) / float(batch_size)))
        for m in range(num_batch):
            # Batch indexes
            begin, end = (
                m * batch_size,
                min((m + 1) * batch_size, x_preprocessed.shape[0]),
            )

            # Create feed_dict
            feed_dict = {self.input_ph: x_preprocessed[begin:end]}
            feed_dict.update(self.feed_dict)

            # Run prediction for the current batch
            layer_output = self._sess.run(layer_tensor, feed_dict=feed_dict)
            results.append(layer_output)

        results_array = np.concatenate(results)

        return results_array

        Return the output of the specified layer for input `x`. `layer` is specified by layer index (between 0 and
        `nb_layers - 1`) or by name. The number of layers can be determined by counting the results returned by
        calling `layer_names`.

        :param x: Input for computing the activations.
        :param layer: Layer for computing the activations.
        :param batch_size: Size of batches.
        :param framework: If true, return the intermediate tensor representation of the activation.
        :return: The output of `layer`, where the first dimension is the batch size corresponding to `x`.
        
art/estimators/classification/tensorflow.py