def _read_graph(schema):
    """Read a DGL Graph object from storage using metadata schema, which is
    a json object describing the DGL graph on disk.

    Parameters:
    -----------
    schema : json object
        json object describing the input graph to read from the disk

    Returns:
    --------
    DGL Graph Object :
        DGL Graph object is created which is read from the disk storage.
    """
    edges = {}
    edge_types = schema[constants.STR_EDGE_TYPE]
    for etype in edge_types:
        efiles = schema[constants.STR_EDGES][etype][constants.STR_DATA]
        src = []
        dst = []
        for fname in efiles:
            if (
                schema[constants.STR_EDGES][etype][constants.STR_FORMAT][
                    constants.STR_NAME
                ]
                == constants.STR_CSV
            ):
                data = read_file(fname, constants.STR_CSV)
            elif (
                schema[constants.STR_EDGES][etype][constants.STR_FORMAT][
                    constants.STR_NAME
                ]
                == constants.STR_PARQUET
            ):
                data = read_file(fname)
            else:
                raise ValueError(
                    f"Unknown edge format for {etype} - {schema[constants.STR_EDGES][etype][constants.STR_FORMAT]}"
                )

                src.append(data[:, 0])
            dst.append(data[:, 1])
        src = np.concatenate(src)
        dst = np.concatenate(dst)
        edges[_etype_str_to_tuple(etype)] = (src, dst)

    g = dgl.heterograph(edges)
    # g = dgl.to_homogeneous(g)

    g.ndata["orig_id"] = g.ndata[dgl.NID]
    g.edata["orig_id"] = g.edata[dgl.EID]

    # read features here.
    for ntype in schema[constants.STR_NODE_TYPE]:
        if ntype in schema[constants.STR_NODE_DATA]:
            for featname, featdata in schema[constants.STR_NODE_DATA][
                ntype
            ].items():
                files = fdata[constants.STR_DATA]
                feats = []
                for fname in files:
                    feats.append(read_file(fname, constants.STR_NUMPY))
                if len(feats) > 0:
                    g.nodes[ntype].data[featname] = th.from_numpy(
                        np.concatenate(feats)
                    )

    # read edge features here.
    for etype in schema[constants.STR_EDGE_TYPE]:
        if etype in schema[constants.STR_EDGE_DATA]:
            for featname, fdata in schema[constants.STR_EDGE_DATA][etype]:
                files = fdata[constants.STR_DATA]
                feats = []
                for fname in files:
                    feats.append(read_file(fname))
                if len(feats) > 0:
                    g.edges[etype].data[featname] = th.from_numpy(
                        np.concatenate(feats)
                    )

    # print from graph
    logging.info(f"|V|= {g.num_nodes()}")
    logging.info(f"|E|= {g.num_edges()}")
    for ntype in g.ntypes:
        for name, data in g.nodes[ntype].data.items():
            if isinstance(data, th.Tensor):
                logging.info(
                    f"Input Graph: nfeat - {ntype}/{name} - data - {data.size()}"
                )

    for c_etype in g.canonical_etypes:
        for name, data in g.edges[c_etype].data.items():
            if isinstance(data, th.Tensor):
                logging.info(
                    f"Input Graph: efeat - {etype}/{name} - data - {g.edges[etype].data[name].size()}"
                )

    return g
Read a DGL Graph object from storage using metadata schema, which is
    a json object describing the DGL graph on disk.

    Parameters:
    -----------
    schema : json object
        json object describing the input graph to read from the disk

    Returns:
    --------
    DGL Graph Object :
        DGL Graph object is created which is read from the disk storage.
    
tools/verify_partitions.py