class_docstr: Args:
      ids (sequence): the IDs of each element
      sources (numpy.ndarray): the ilocs of the source of each edge
      targets (numpy.ndarray): the ilocs of the target of each edge
      weight (numpy.ndarray): the weight of each edge
      type_info (list of tuple of type name, numpy array): the associated feature vectors of each type, where the size of the first dimension defines the elements of that type
      number_of_nodes (int): the total number of nodes in the graph
class_docstr_tok: ["Args",":","ids","(","sequence",")",":","the","IDs","of","each","element","sources","(","numpy.ndarray",")",":","the","ilocs","of","the","source","of","each","edge","targets","(","numpy.ndarray",")",":","the","ilocs","of","the","target","of","each","edge","weight","(","numpy.ndarray",")",":","the","weight","of","each","edge","type_info","(","list","of","tuple","of","type","name",",","numpy","array",")",":","the","associated","feature","vectors","of","each","type",",","where","the","size","of","the","first","dimension","defines","the","elements","of","that","type","number_of_nodes","(","int",")",":","the","total","number","of","nodes","in","the","graph"]
code: def __init__(
      self, ids, sources, targets, weights, type_info, number_of_nodes
  ):
      super().__init__(ids, type_info)
  
      for name, column in {
          "sources": sources,
          "targets": targets,
          "weights": weights,
      }.items():
          if not isinstance(column, np.ndarray):
              raise TypeError(
                  f"{name}: expected a NumPy ndarray, found {type(column).__name__}"
              )
  
          if len(column.shape) != 1:
              raise TypeError(
                  f"{name}: expected rank-1 array, found shape {column.shape}"
              )
  
          if len(column) != len(self._id_index):
              raise TypeError(
                  f"{name}: expected length {len(self._id_index)} to match IDs, found length {len(column)}"
              )
  
      self.sources = sources
      self.targets = targets
      self.weights = weights
      self.number_of_nodes = number_of_nodes
  
      # These are lazily initialized, to only pay the (construction) time and memory cost when
      # actually using them
      self._edges_dict = (
          self._edges_in_dict
      ) = self._edges_out_dict = None
  
      # when there's no neighbors for something, an empty array should be returned; this uses a
      # tiny dtype to minimise unnecessary type promotion (e.g. if this is used with an int32
      # array, the result will still be int32).
      self._empty_ilocs = np.array([], dtype=np.uint8)
  
imports: import itertools
  from collections import defaultdict
  import numpy
  import pandas
  import scipy.sparse
  from ..globalvar import SOURCE, TARGET, WEIGHT, TYPE_ATTR_NAME
  from .validation import require_dataframe_has_columns, comma_sep
label_desc: Use image node_id 1 to create a new EdgeData object from inherited base classes: ElementData with example: obj = EdgeData(ids, sources, targets, weights, type_info, number_of_nodes)