code: def feature_steered_convolution_layer(
      data,
      neighbors,
      sizes,
      translation_invariant=True,
      num_weight_matrices=8,
      num_output_channels=None,
      initializer=tf.keras.initializers.TruncatedNormal(stddev=0.1),
      name="graph_convolution_feature_steered_convolution",
      var_name=None,
  ):
      # pyformat: disable
      """Wraps the function `feature_steered_convolution` as a TensorFlow layer.
  
      The shorthands used below are
        `V`: The number of vertices.
        `C`: The number of channels in the input data.
  
      Note:
        In the following, A1 to An are optional batch dimensions.
  
      Args:
        data: A `float` tensor with shape `[A1, ..., An, V, C]`.
        neighbors: A SparseTensor with the same type as `data` and with shape
          `[A1, ..., An, V, V]` representing vertex neighborhoods. The neighborhood
          of a vertex defines the support region for convolution. For a mesh, a
          common choice for the neighborhood of vertex `i` would be the vertices in
          the K-ring of `i` (including `i` itself). Each vertex must have at least
          one neighbor. For a faithful implementation of the FeaStNet paper,
          neighbors should be a row-normalized weight matrix corresponding to the
          graph adjacency matrix with self-edges:
          `neighbors[A1, ..., An, i, j] > 0` if vertex `i` and `j` are neighbors,
          `neighbors[A1, ..., An, i, i] > 0` for all `i`, and
          `sum(neighbors, axis=-1)[A1, ..., An, i] == 1.0` for all `i`.
          These requirements are relaxed in this implementation.
        sizes: An `int` tensor of shape `[A1, ..., An]` indicating the true input
          sizes in case of padding (`sizes=None` indicates no padding).
          `sizes[A1, ..., An] <= V`. If `data` and `neighbors` are 2-D, `sizes` will
          be ignored. As an example, consider an input consisting of three graphs
          `G0`, `G1`, and `G2` with `V0`, `V1` and `V2` vertices respectively. The
          padded input would have the following shapes: `data.shape = [3, V, C]`,
          and `neighbors.shape = [3, V, V]`, where `V = max([V0, V1, V2])`. The true
          sizes of each graph will be specified by `sizes=[V0, V1, V2]`.
          `data[i, :Vi, :]` and `neighbors[i, :Vi, :Vi]` will be the vertex and
          neighborhood data of graph `Gi`. The `SparseTensor` `neighbors` should
          have no nonzero entries in the padded regions.
        translation_invariant: A `bool`. If `True` the assignment of features to
          weight matrices will be invariant to translation.
        num_weight_matrices: An `int` specifying the number of weight matrices used
          in the convolution.
        num_output_channels: An optional `int` specifying the number of channels in
          the output. If `None` then `num_output_channels = C`.
        initializer: An initializer for the trainable variables.
        name: A (name_scope) name for this op. Passed through to
          feature_steered_convolution().
        var_name: A (var_scope) name for the variables. Defaults to
          `graph_convolution_feature_steered_convolution_weights`.
  
      Returns:
        Tensor with shape `[A1, ..., An, V, num_output_channels]`.
      """
      # pyformat: enable
      with tf.compat.v1.variable_scope(
          var_name,
          default_name="graph_convolution_feature_steered_convolution_weights",
      ):
          # Skips shape validation to avoid redundancy with
          # feature_steered_convolution().
          data = tf.convert_to_tensor(value=data)
  
          in_channels = tf.compat.dimension_value(data.shape[-1])
          if num_output_channels is None:
              out_channels = in_channels
          else:
              out_channels = num_output_channels
  
          var_u = tf.compat.v1.get_variable(
              shape=(in_channels, num_weight_matrices),
              dtype=data.dtype,
              initializer=initializer,
              name="u",
          )
          if translation_invariant:
              var_v = -var_u
          else:
              var_v = tf.compat.v1.get_variable(
                  shape=(in_channels, num_weight_matrices),
                  dtype=data.dtype,
                  initializer=initializer,
                  name="v",
              )
          var_c = tf.compat.v1.get_variable(
              shape=(num_weight_matrices),
              dtype=data.dtype,
              initializer=initializer,
              name="c",
          )
          var_w = tf.compat.v1.get_variable(
              shape=(num_weight_matrices, in_channels, out_channels),
              dtype=data.dtype,
              initializer=initializer,
              name="w",
          )
          var_b = tf.compat.v1.get_variable(
              shape=(out_channels),
              dtype=data.dtype,
              initializer=initializer,
              name="b",
          )
  
          return gc.feature_steered_convolution(
              data=data,
              neighbors=neighbors,
              sizes=sizes,
              var_u=var_u,
              var_v=var_v,
              var_c=var_c,
              var_w=var_w,
              var_b=var_b,
              name=name,
          )
  
file_path: graphics/tensorflow_graphics/nn/layer/graph_convolution.py
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  import tensorflow
  import tensorflow_graphics.geometry.convolution.graph_convolution
  from tensorflow_graphics.util import export_api
label_desc: Use image node_id 1 for calling a global function with example usage: feature_steered_convolution_layer(data, neighbors, sizes, translation_invariant, num_weight_matrices, num_output_channels, initializer, name, var_name) and returns: gc