code: def load_partition_book(part_config, part_id):
      """Load a graph partition book from the partition config file.
  
      Parameters
      ----------
      part_config : str
          The path of the partition config file.
      part_id : int
          The partition ID.
  
      Returns
      -------
      GraphPartitionBook
          The global partition information.
      str
          The graph name
      dict
          The node types
      dict
          The edge types
      """
      part_metadata = _load_part_config(part_config)
      assert "num_parts" in part_metadata, "num_parts does not exist."
      assert (
          part_metadata["num_parts"] > part_id
      ), "part {} is out of range (#parts: {})".format(
          part_id, part_metadata["num_parts"]
      )
      num_parts = part_metadata["num_parts"]
      assert (
          "num_nodes" in part_metadata
      ), "cannot get the number of nodes of the global graph."
      assert (
          "num_edges" in part_metadata
      ), "cannot get the number of edges of the global graph."
      assert "node_map" in part_metadata, "cannot get the node map."
      assert "edge_map" in part_metadata, "cannot get the edge map."
      assert "graph_name" in part_metadata, "cannot get the graph name"
  
      # If this is a range partitioning, node_map actually stores a list, whose elements
      # indicate the boundary of range partitioning. Otherwise, node_map stores a filename
      # that contains node map in a NumPy array.
      node_map = part_metadata["node_map"]
      edge_map = part_metadata["edge_map"]
      if isinstance(node_map, dict):
          for key in node_map:
              is_range_part = isinstance(node_map[key], list)
              break
      elif isinstance(node_map, list):
          is_range_part = True
          node_map = {DEFAULT_NTYPE: node_map}
      else:
          is_range_part = False
      if isinstance(edge_map, list):
          edge_map = {DEFAULT_ETYPE: edge_map}
  
      ntypes = {DEFAULT_NTYPE: 0}
      etypes = {DEFAULT_ETYPE: 0}
      if "ntypes" in part_metadata:
          ntypes = part_metadata["ntypes"]
      if "etypes" in part_metadata:
          etypes = part_metadata["etypes"]
  
      if isinstance(node_map, dict):
          for key in node_map:
              assert (
                  key in ntypes
              ), "The node type {} is invalid".format(key)
      if isinstance(edge_map, dict):
          for key in edge_map:
              assert (
                  key in etypes
              ), "The edge type {} is invalid".format(key)
  
      if not is_range_part:
          raise TypeError(
              "Only RangePartitionBook is supported currently."
          )
  
      node_map = _get_part_ranges(node_map)
      edge_map = _get_part_ranges(edge_map)
  
      # Sort the node/edge maps by the node/edge type ID.
      node_map = dict(
          sorted(node_map.items(), key=lambda x: ntypes[x[0]])
      )
      edge_map = dict(
          sorted(edge_map.items(), key=lambda x: etypes[x[0]])
      )
  
      def _assert_is_sorted(id_map):
          id_ranges = np.array(list(id_map.values()))
          ids = []
          for i in range(num_parts):
              ids.append(id_ranges[:, i, :])
          ids = np.array(ids).flatten()
          assert np.all(
              ids[:-1] <= ids[1:]
          ), f"The node/edge map is not sorted: {ids}"
  
      _assert_is_sorted(node_map)
      _assert_is_sorted(edge_map)
  
      return (
          RangePartitionBook(
              part_id, num_parts, node_map, edge_map, ntypes, etypes
          ),
          part_metadata["graph_name"],
          ntypes,
          etypes,
      )
  
imports: import json
  import logging
  import os
  import time
  import numpy
  import torch
  from ..None import backend
  from ..base import DGLError, EID, ETYPE, NID, NTYPE
  from ..convert import to_homogeneous
  from ..data.utils import load_graphs, load_tensors, save_graphs, save_tensors
  from ..partition import get_peak_mem, metis_partition_assignment, partition_graph_with_halo
  from ..random import choice
  from ..transforms import sort_csc_by_tag, sort_csr_by_tag
  from .constants import DEFAULT_ETYPE, DEFAULT_NTYPE
  from .graph_partition_book import _etype_str_to_tuple, _etype_tuple_to_str, RangePartitionBook
label_desc: Use image node_id 10 for calling a global function with example usage: load_partition_book(part_config, part_id) and returns: RangePartitionBook,  part_metadata,  ntypes,  etypes