class_docstr: Positional encoding of points in a neighborhood.
class_docstr_tok: ["Positional","encoding","of","points","in","a","neighborhood","."]
docstr: Local Spatial Encoding (locSE) and attentive pooling of features.
  
  Args:
      x_j (Tensor): neighboors features (K,d)
      pos_i (Tensor): centroid position (repeated) (K,3)
      pos_j (Tensor): neighboors positions (K,3)
      index (Tensor): index of centroid positions
          (e.g. [0,...,0,1,...,1,...,N,...,N])
  
  Returns:
      (Tensor): locSE weighted by feature attention scores.
docstr_tok: ["Local","Spatial","Encoding","(","locSE",")","and","attentive","pooling","of","features",".","Args",":","x_j","(","Tensor",")",":","neighboors","features","(","K",",","d",")","pos_i","(","Tensor",")",":","centroid","position","(","repeated",")","(","K,3",")","pos_j","(","Tensor",")",":","neighboors","positions","(","K,3",")","index","(","Tensor",")",":","index","of","centroid","positions","(","e.g",".","[","0",",","...",",0,1",",","...",",1",",","...",",","N",",","...",",","N","]",")","Returns",":","(","Tensor",")",":","locSE","weighted","by","feature","attention","scores","."]
code: def message(
      self, x_j: Tensor, pos_i: Tensor, pos_j: Tensor, index: Tensor
  ) -> Tensor:
      """Local Spatial Encoding (locSE) and attentive pooling of features.
  
      Args:
          x_j (Tensor): neighboors features (K,d)
          pos_i (Tensor): centroid position (repeated) (K,3)
          pos_j (Tensor): neighboors positions (K,3)
          index (Tensor): index of centroid positions
              (e.g. [0,...,0,1,...,1,...,N,...,N])
  
      Returns:
          (Tensor): locSE weighted by feature attention scores.
  
      """
      # Encode local neighboorhod structural information
      pos_diff = pos_j - pos_i
      distance = torch.sqrt((pos_diff * pos_diff).sum(1, keepdim=True))
      relative_infos = torch.cat(
          [pos_i, pos_j, pos_diff, distance], dim=1
      )  # N * K, d
      local_spatial_encoding = self.mlp_encoder(
          relative_infos
      )  # N * K, d
      local_features = torch.cat(
          [x_j, local_spatial_encoding], dim=1
      )  # N * K, 2d
  
      # Attention will weight the different features of x
      # along the neighborhood dimension.
      att_features = self.mlp_attention(local_features)  # N * K, d_out
      att_scores = softmax(att_features, index=index)  # N * K, d_out
  
      return att_scores * local_features
  
imports: import os.path
  import torch
  import torch.nn.functional
  from torch import Tensor
  from torch.nn import Linear
  from tqdm import tqdm
  import torch_geometric.transforms
  from torch_geometric.datasets import ModelNet
  from torch_geometric.loader import DataLoader
  from torch_geometric.nn import MLP
  from torch_geometric.nn.aggr import MaxAggregation
  from torch_geometric.nn.conv import MessagePassing
  from torch_geometric.nn.pool import knn_graph
  from torch_geometric.nn.pool.decimation import decimation_indices
  from torch_geometric.typing import WITH_TORCH_CLUSTER
  from torch_geometric.utils import softmax
label_desc: Use image node_id 3 for calling the LocalFeatureAggregation obj's underlying member method code with example usage: obj.message(x_j, pos_i, pos_j, index) and returns: unknown