def custom_bfs(graph, start_node, direction="forward", edge_type="causes_or_promotes"):
    """
    Explores graph and gets the subgraph containing all the nodes that are reached via BFS from start_node
    Parameters
    ----------
    graph - nx.DiGraph to explore
    start_node - root of the BFS search
    direction - forward, reverse, or any. Controls what direction BFS searches in
    edge_type - only explore along edges of this type (can be "any")
    Returns
    -------
    subgraph with nodes explored
    """
    # Using a list because we want to have the explored elements returned later.
    queue = [start_node]
    cur_index = 0

    def do_bfs(element):
        nonlocal cur_index
        if direction == "reverse" or direction == "any":
            for start, end, type in graph.in_edges(element, "type"):
                if start not in queue and (edge_type == "any" or type == edge_type):
                    queue.append(start)
        if direction == "forward" or direction == "any":
            for start, end, type in graph.out_edges(element, "type"):
                if end not in queue and (edge_type == "any" or type == edge_type):
                    queue.append(end)

    do_bfs(start_node)

    while cur_index < len(queue):
        do_bfs(queue[cur_index])
        cur_index = cur_index + 1

    return graph.subgraph(queue)