class_docstr: Description
  -----------
  GraphConv with edge weights on homogeneous graphs.
  If edge weights are not given, directly call GraphConv instead.
  
  Parameters
  ----------
  graph : DGLGraph
      The graph to perform this operation.
  n_feat : torch.Tensor
      The node features
  e_feat : torch.Tensor, optional
      The edge features. Default: :obj:`None`
code: def forward(self, graph: DGLGraph, n_feat, e_feat=None):
      if e_feat is None:
          return super(WeightedGraphConv, self).forward(graph, n_feat)
  
      with graph.local_scope():
          if self.weight is not None:
              n_feat = torch.matmul(n_feat, self.weight)
          src_norm = torch.pow(
              graph.out_degrees().float().clamp(min=1), -0.5
          )
          src_norm = src_norm.view(-1, 1)
          dst_norm = torch.pow(
              graph.in_degrees().float().clamp(min=1), -0.5
          )
          dst_norm = dst_norm.view(-1, 1)
          n_feat = n_feat * src_norm
          graph.ndata["h"] = n_feat
          graph.edata["e"] = e_feat
          graph.update_all(fn.u_mul_e("h", "e", "m"), fn.sum("m", "h"))
          n_feat = graph.ndata.pop("h")
          n_feat = n_feat * dst_norm
          if self.bias is not None:
              n_feat = n_feat + self.bias
          if self._activation is not None:
              n_feat = self._activation(n_feat)
          return n_feat
  
imports: import dgl
  import dgl.function
  import scipy.sparse
  import torch
  import torch.nn
  import torch.nn.functional
  from dgl import DGLGraph
  from dgl.nn import AvgPooling, GraphConv, MaxPooling
  from dgl.ops import edge_softmax
  from functions import edge_sparsemax
  from torch import Tensor
  from torch.nn import Parameter
  from utils import get_batch_id, topk
label_desc: Use image node_id 1 for calling the WeightedGraphConv obj's underlying member method code with example usage: obj.forward(graph, n_feat, e_feat) and returns: super, n_feat