nodes: 0, module; 1, function_definition; 2, function_name:nx_dag_node_rank; 3, parameters; 4, block; 5, identifier:graph; 6, default_parameter; 7, expression_statement; 8, import_statement; 9, expression_statement; 10, expression_statement; 11, expression_statement; 12, if_statement; 13, identifier:nodes; 14, None; 15, comment:"""
      Returns rank of nodes that define the "level" each node is on in a
      topological sort. This is the same as the Graphviz dot rank.
  
      Ignore:
          simple_graph = ut.simplify_graph(exi_graph)
          adj_dict = ut.nx_to_adj_dict(simple_graph)
          import plottool as pt
          pt.qt4ensure()
          pt.show_nx(graph)
  
      Example:
          >>> # ENABLE_DOCTEST
          >>> from utool.util_graph import *  # NOQA
          >>> import utool as ut
          >>> adj_dict = {0: [5], 1: [5], 2: [1], 3: [4], 4: [0], 5: [], 6: [4], 7: [9], 8: [6], 9: [1]}
          >>> nodes = [2, 1, 5]
          >>> f_graph = ut.nx_from_adj_dict(adj_dict, nx.DiGraph)
          >>> graph = f_graph.reverse()
          >>> #ranks = ut.nx_dag_node_rank(graph, nodes)
          >>> ranks = ut.nx_dag_node_rank(graph, nodes)
          >>> result = ('ranks = %r' % (ranks,))
          >>> print(result)
          ranks = [3, 2, 1]
      """; 16, aliased_import; 17, assignment; 18, assignment; 19, assignment; 20, comparison_operator:nodes is None; 21, block; 22, else_clause; 23, dotted_name; 24, identifier:ut; 25, identifier:source; 26, subscript; 27, identifier:longest_paths; 28, call; 29, identifier:node_to_rank; 30, call; 31, identifier:nodes; 32, None; 33, return_statement; 34, block; 35, identifier:utool; 36, call; 37, integer:0; 38, identifier:dict; 39, argument_list; 40, attribute; 41, argument_list; 42, identifier:node_to_rank; 43, expression_statement; 44, return_statement; 45, identifier:list; 46, argument_list; 47, list_comprehension; 48, identifier:ut; 49, identifier:map_dict_vals; 50, identifier:len; 51, identifier:longest_paths; 52, assignment; 53, identifier:ranks; 54, call; 55, tuple; 56, for_in_clause; 57, identifier:ranks; 58, call; 59, attribute; 60, argument_list; 61, identifier:target; 62, call; 63, identifier:target; 64, call; 65, attribute; 66, argument_list; 67, identifier:ut; 68, identifier:nx_source_nodes; 69, identifier:graph; 70, identifier:dag_longest_path; 71, argument_list; 72, attribute; 73, argument_list; 74, identifier:ut; 75, identifier:dict_take; 76, identifier:node_to_rank; 77, identifier:nodes; 78, identifier:graph; 79, identifier:source; 80, identifier:target; 81, identifier:graph; 82, identifier:nodes
code: def nx_dag_node_rank(graph, nodes=None):
      """
      Returns rank of nodes that define the "level" each node is on in a
      topological sort. This is the same as the Graphviz dot rank.
  
      Ignore:
          simple_graph = ut.simplify_graph(exi_graph)
          adj_dict = ut.nx_to_adj_dict(simple_graph)
          import plottool as pt
          pt.qt4ensure()
          pt.show_nx(graph)
  
      Example:
          >>> # ENABLE_DOCTEST
          >>> from utool.util_graph import *  # NOQA
          >>> import utool as ut
          >>> adj_dict = {0: [5], 1: [5], 2: [1], 3: [4], 4: [0], 5: [], 6: [4], 7: [9], 8: [6], 9: [1]}
          >>> nodes = [2, 1, 5]
          >>> f_graph = ut.nx_from_adj_dict(adj_dict, nx.DiGraph)
          >>> graph = f_graph.reverse()
          >>> #ranks = ut.nx_dag_node_rank(graph, nodes)
          >>> ranks = ut.nx_dag_node_rank(graph, nodes)
          >>> result = ('ranks = %r' % (ranks,))
          >>> print(result)
          ranks = [3, 2, 1]
      """
      import utool as ut
      source = list(ut.nx_source_nodes(graph))[0]
      longest_paths = dict([(target, dag_longest_path(graph, source, target))
                            for target in graph.nodes()])
      node_to_rank = ut.map_dict_vals(len, longest_paths)
      if nodes is None:
          return node_to_rank
      else:
          ranks = ut.dict_take(node_to_rank, nodes)
          return ranks