def horizontal_positions(docgraph, sentence_root=None):
    """return map: node ID -> first token index (int) it covers"""
    # calculate positions for the whole graph
    root_cond = (sentence_root is None) or (sentence_root == docgraph.root)
    if root_cond or ('tokens' not in docgraph.node[sentence_root]):
        sentence_root = docgraph.root
        token_nodes = docgraph.tokens
        path = {}
    else:  # calculate positions only for the given sentence subgraph
        token_nodes = docgraph.node[sentence_root]['tokens']
        path = {sentence_root: 0}

    for i, token_node in enumerate(token_nodes):
        start_node = token_node
        while get_parents(docgraph, start_node, strict=True):
            if start_node not in path:
                path[start_node] = i
            start_node = get_parents(docgraph, start_node, strict=True)[0]
    return path