code: def node_type_subgraph(graph, ntypes, output_device=None):
      """Return the subgraph induced on given node types.
  
      A node-type-induced subgraph contains all the nodes of the given subset of
      the node types of a graph and any edges whose endpoints are both in this subset.
      In addition to extracting the subgraph, DGL also copies the features of the
      extracted nodes and edges to the resulting graph.
      The copy is *lazy* and incurs data movement only when needed.
  
      Parameters
      ----------
      graph : DGLGraph
          The graph to extract subgraphs from.
      ntypes : list[str]
          The type names of the nodes in the subgraph.
      output_device : Framework-specific device context object, optional
          The output device.  Default is the same as the input graph.
  
      Returns
      -------
      G : DGLGraph
          The subgraph.
  
      Notes
      -----
  
      This function discards the batch information. Please use
      :func:`dgl.DGLGraph.set_batch_num_nodes`
      and :func:`dgl.DGLGraph.set_batch_num_edges` on the transformed graph
      to maintain the information.
  
      Examples
      --------
      The following example uses PyTorch backend.
  
      >>> import dgl
      >>> import torch
  
      Instantiate a heterograph.
  
      >>> g = dgl.heterograph({
      >>>     ('user', 'plays', 'game'): ([0, 1, 1, 2], [0, 0, 2, 1]),
      >>>     ('user', 'follows', 'user'): ([0, 1, 1], [1, 2, 2])
      >>> })
      >>> # Set node features
      >>> g.nodes['user'].data['h'] = torch.tensor([[0.], [1.], [2.]])
  
      Get subgraphs.
  
      >>> sub_g = g.node_type_subgraph(['user'])
      >>> print(sub_g)
      Graph(num_nodes=3, num_edges=3,
            ndata_schemes={'h': Scheme(shape=(1,), dtype=torch.float32)}
            edata_schemes={})
  
      Get the extracted node features.
  
      >>> sub_g.nodes['user'].data['h']
      tensor([[0.],
              [1.],
              [2.]])
  
      See Also
      --------
      edge_type_subgraph
      """
      ntid = [graph.get_ntype_id(ntype) for ntype in ntypes]
      stids, dtids, etids = graph._graph.metagraph.edges("eid")
      stids, dtids, etids = (
          stids.tonumpy(),
          dtids.tonumpy(),
          etids.tonumpy(),
      )
      etypes = []
      for stid, dtid, etid in zip(stids, dtids, etids):
          if stid in ntid and dtid in ntid:
              etypes.append(graph.canonical_etypes[etid])
      if len(etypes) == 0:
          raise DGLError(
              "There are no edges among nodes of the specified types."
          )
      return edge_type_subgraph(
          graph, etypes, output_device=output_device
      )
  
file_path: dgl/python/dgl/subgraph.py
imports: from collections.abc import Mapping
  from .None import backend, graph_index, heterograph_index, utils
  from ._ffi.function import _init_api
  from .base import DGLError
  from .heterograph import DGLGraph
  from .utils import context_of, recursive_apply
label_desc: Use image node_id 7 for calling a global function with example usage: node_type_subgraph(graph, ntypes, output_device) and returns: edge_type_subgraph