class_docstr: An abstract base class to access edges from a remote graph store.
  
  Args:
      edge_attr_cls (EdgeAttr, optional): A user-defined
          :class:`EdgeAttr` class to customize the required attributes and
          their ordering to uniquely identify edges. (default: :obj:`None`)
class_docstr_tok: ["An","abstract","base","class","to","access","edges","from","a","remote","graph","store",".","Args",":","edge_attr_cls","(","EdgeAttr",",","optional",")",":","A","user-defined",":","class",":","`","EdgeAttr","`","class","to","customize","the","required","attributes","and","their","ordering","to","uniquely","identify","edges",".","(","default",":",":","obj",":","`","None","`",")"]
code: def _edge_to_layout(
      self,
      attr: EdgeAttr,
      layout: EdgeLayout,
      store: bool = False,
  ) -> Tuple[Tensor, Tensor, OptTensor]:
      (row, col), perm = self.get_edge_index(attr), None
  
      if layout == EdgeLayout.COO:  # COO output requested:
          if attr.layout == EdgeLayout.CSR:  # CSR->COO
              row = ptr2index(row)
          elif attr.layout == EdgeLayout.CSC:  # CSC->COO
              col = ptr2index(col)
  
      elif layout == EdgeLayout.CSR:  # CSR output requested:
          if attr.layout == EdgeLayout.CSC:  # CSC->COO
              col = ptr2index(col)
  
          if attr.layout != EdgeLayout.CSR:  # COO->CSR
              num_rows = (
                  attr.size[0] if attr.size else int(row.max()) + 1
              )
              row, perm = index_sort(row, max_value=num_rows)
              col = col[perm]
              row = index2ptr(row, num_rows)
  
      else:  # CSC output requested:
          if attr.layout == EdgeLayout.CSR:  # CSR->COO
              row = ptr2index(row)
  
          if attr.layout != EdgeLayout.CSC:  # COO->CSC
              if hasattr(self, "meta") and self.meta.get(
                  "is_hetero", False
              ):
                  # Hotfix for `LocalGraphStore`, where in heterogeneous
                  # graphs, edge indices for different edge types have
                  # continuous indices not starting at 0.
                  num_cols = int(col.max()) + 1
              elif attr.size is not None:
                  num_cols = attr.size[1]
              else:
                  num_cols = int(col.max()) + 1
  
              if not attr.is_sorted:  # Not sorted by destination.
                  col, perm = index_sort(col, max_value=num_cols)
                  row = row[perm]
              col = index2ptr(col, num_cols)
  
      if attr.layout != layout and store:
          attr = copy.copy(attr)
          attr.layout = layout
          if perm is not None:
              attr.is_sorted = False
          self.put_edge_index((row, col), attr)
  
      return row, col, perm
  
imports: import copy
  from abc import abstractmethod
  from collections import defaultdict
  from dataclasses import dataclass
  from enum import Enum
  from typing import Any, Dict, List, Optional, Tuple
  from torch import Tensor
  from torch_geometric.typing import EdgeTensorType, EdgeType, OptTensor
  from torch_geometric.utils import index_sort
  from torch_geometric.utils.mixin import CastMixin
  from torch_geometric.utils.sparse import index2ptr, ptr2index
label_desc: Use image node_id 16 for calling the GraphStore obj's underlying member method code with example usage: obj._edge_to_layout(attr, layout, store) and returns: row,  col,  perm