def is_endpoint(G, node, strict=True):
    """
    Return True if the node is a "real" endpoint of an edge in the network,     otherwise False. OSM data includes lots of nodes that exist only as points     to help streets bend around curves. An end point is a node that either:     1) is its own neighbor, ie, it self-loops.     2) or, has no incoming edges or no outgoing edges, ie, all its incident         edges point inward or all its incident edges point outward.     3) or, it does not have exactly two neighbors and degree of 2 or 4.     4) or, if strict mode is false, if its edges have different OSM IDs. 
    Parameters
    ----------
    G : networkx multidigraph

    node : int
        the node to examine
    strict : bool
        if False, allow nodes to be end points even if they fail all other rules         but have edges with different OSM IDs

    Returns
    -------
    bool

    """
    neighbors = set(list(G.predecessors(node)) + list(G.successors(node)))
    n = len(neighbors)
    d = G.degree(node)
    if node in neighbors:
        return True
    elif G.out_degree(node) == 0 or G.in_degree(node) == 0:
        return True
    elif not (n == 2 and (d == 2 or d == 4)):
        return True
    elif not strict:
        osmids = []
        for u in G.predecessors(node):
            for key in G[u][node]:
                osmids.append(G.edges[u, node, key]['osmid'])
        for v in G.successors(node):
            for key in G[node][v]:
                osmids.append(G.edges[node, v, key]['osmid'])
        return len(set(osmids)) > 1
    else:
        return False
