コード例 #1
0
ファイル: checkerboard.py プロジェクト: florisvb/flydra
def find_subgraph_similar_direction(G, source=None, direction_eps_radians=None, already_done=None):
    """
    originally from networkx/search.py

    added traverse_node_callback() stuff.
    """

    neighbors = G.neighbors

    seen = {}  # nodes seen
    succ = {}

    queue = [source]  # use as LIFO queue
    direction_radians = None
    already_did_first_edge = False
    debug = False
    while queue:
        v = queue[-1]
        if v not in seen:
            seen[v] = True
            succ[v] = []
        done = 1
        for w in neighbors(v):
            if w not in seen:

                this_direction_radians = w.get_direction_from(v)
                if direction_radians is None:
                    # testing first edge

                    for test_graph in already_done:
                        # check already done graphs to see if we have this edge
                        already_did_first_edge = test_graph.has_edge(v, w)
                        if already_did_first_edge:
                            break

                    # first edge
                    if not already_did_first_edge:
                        direction_radians = this_direction_radians

                if (not already_did_first_edge) and angles_near(
                    this_direction_radians, direction_radians, direction_eps_radians, mod_pi=True
                ):
                    queue.append(w)
                    succ[v].append(w)
                    done = 0
                    break
                else:
                    seen[w] = True
        if done == 1:
            queue.pop()
    result = None
    if len(succ) > 1:
        result = NX.Graph(succ)
        if 0:
            print "source", source
            print succ
            print
    return result
コード例 #2
0
ファイル: checkerboard.py プロジェクト: florisvb/flydra
def points2graph(
    x, y, distance_thresh=1.5, angle_thresh=30 * D2R, show_clusters=False, show_clusters_frame=None, aspect_ratio=1.0
):
    x = numpy.array(x)
    y = numpy.array(y)
    tri = delaunay.Triangulation(x, y)
    nodes = [CornerNode(xi, yi, i, aspect_ratio=aspect_ratio) for i, (xi, yi) in enumerate(zip(x, y))]

    segx = []
    segy = []
    vert_inds = []
    for node in tri.triangle_nodes:
        for i in range(3):
            segx.append((x[node[i]], x[node[(i + 1) % 3]]))
            segy.append((y[node[i]], y[node[(i + 1) % 3]]))
            vert_inds.append((node[i], node[(i + 1) % 3]))

        if 0:
            # find and remove hypotenuse
            dist2 = [(segx[i][0] - segx[i][1]) ** 2 + (segy[i][0] - segy[i][1]) ** 2 for i in range(-3, 0)]
            longest_ind = -3 + numpy.argmax(dist2)
            del segx[longest_ind]
            del segy[longest_ind]
            del vert_inds[longest_ind]

    # Discard duplicates.  (This could be acheived by more careful
    # attention at the triangulation stage.)
    idx = 0
    while idx < len(vert_inds):
        test = vert_inds[idx]
        idx += 1

        remove = []
        for cmpi in range(idx, len(vert_inds)):
            if test == vert_inds[cmpi]:
                remove.append(cmpi)
        remove.reverse()
        for i in remove:
            del vert_inds[i]
            del segx[i]
            del segy[i]

    adjacency = numpy.zeros((len(x), len(x)), dtype=numpy.uint32)
    graph = NX.Graph()
    for test_seg in vert_inds:
        i, j = test_seg
        graph.add_edge(nodes[i], nodes[j])
        # The graph is not directed, so we don't need to add (j,i).

    if 1:
        # remove edges not belonging to 2 shortest distance clusters
        edges = graph.edges()

        directions = [edge[0].get_direction_from(edge[1]) for edge in edges]
        directions = numpy.array(directions) % numpy.pi
        distance = [edge[0].get_distance_from(edge[1]) for edge in edges]

        obs = numpy.array([directions, distance]).T
        distance_max = obs[:, 1].max()
        scale = [[1, numpy.pi / distance_max]]
        scaled_obs = obs * scale

        if 1:
            # do clustering on Cartesian grid.

            r = obs[:, 1]
            median_r = numpy.median(r)
            x = r * numpy.cos(obs[:, 0] * 2)  # double angle to go around full circle
            y = r * numpy.sin(obs[:, 0] * 2)  # double angle to go around full circle
            if 0 and show_clusters:
                pylab.figure()
                pylab.plot(x, y, ".")
                ax = pylab.gca()
                ax.set_aspect("equal")

                print "median_r", median_r
                print "%d cut" % len(numpy.nonzero(r > median_r * distance_thresh)[0])

            # threshold large distances to origin
            good_cond = r <= median_r * distance_thresh
            good_idx = numpy.nonzero(good_cond)[0]

            cartesian_obs = numpy.array([x, y]).T
            # filter data
            cartesian_obs_use = cartesian_obs[good_idx]

            # 4 clusters: 2 for each main direction, 2 for diagonals
            # cartesian_clusters, labels = scipy.cluster.vq.kmeans2( cartesian_obs, 4)
            # 5 clusters: same as above, plus trash
            if 0:
                cartesian_clusters, labels = scipy.cluster.vq.kmeans2(cartesian_obs, 5, iter=100, minit="points")
            else:
                # initial guesses
                cluster_guesses = numpy.array([[median_r, 0], [0, median_r], [-median_r, 0], [0, -median_r]])
                cartesian_clusters_use, labels_use = scipy.cluster.vq.kmeans2(
                    cartesian_obs_use, cluster_guesses, iter=100, minit="matrix"
                )
                # add new cluster with filtered data
                new_label = numpy.max(labels_use) + 1
                cartesian_clusters = numpy.zeros((5, 2))
                cartesian_clusters[:-1, :] = cartesian_clusters_use
                labels = new_label * numpy.ones((cartesian_obs.shape[0],), dtype=labels_use.dtype)
                labels[good_idx] = labels_use
                cartesian_clusters_center = numpy.array(cartesian_clusters, copy=True)
                ## print 'cartesian_clusters'
                ## print cartesian_clusters
                ## print
            x = numpy.array(cartesian_clusters[:, 0], copy=True)
            y = numpy.array(cartesian_clusters[:, 1], copy=True)
            r = numpy.sqrt(x ** 2 + y ** 2)
            theta = numpy.arccos(y / r, x / r)
            theta[r == 0] = 0  # eliminate nan
            theta = theta / 2  # get back to mod pi angles
            clusters = numpy.array([theta, r]).T

        if show_clusters:
            n_clusters = len(clusters)
            pylab.figure()

            ax = pylab.subplot(2, 1, 1)
            for i in range(n_clusters):
                cluster_cond = labels == i
                this_obs = obs[cluster_cond]
                color = get_color(i)
                pylab.plot(this_obs[:, 0] / 2.0, this_obs[:, 1], ".", mec=color, mfc=color)
                # pylab.plot([clusters[i][0]],[clusters[i][1]],'ko')
                print "label", i, [clusters[i][0]], [clusters[i][1]]
            if show_clusters_frame is not None:
                pylab.title("frame %d" % show_clusters_frame)

            ax = pylab.subplot(2, 1, 2)
            for i in range(n_clusters):
                cluster_cond = labels == i
                this_obs = obs[cluster_cond]
                color = get_color(i)
                pylab.plot(cartesian_obs[cluster_cond, 0], cartesian_obs[cluster_cond, 1], ".", mec=color, mfc=color)
                # print i,[cartesian_clusters_center[i][0]],[cartesian_clusters_center[i][1]]
                pylab.plot([cartesian_clusters_center[i][0]], [cartesian_clusters_center[i][1]], "ko")
            ax.set_aspect("equal")
            pylab.show()
            # sys.exit()

        cluster_distances = clusters[:, 1]
        if show_clusters:
            print "cluster_distances", cluster_distances
        cluster_idxs = numpy.argsort(cluster_distances)
        shortest_idxs = cluster_idxs[1:3]  # shortest is trash at 0, ignore it and take 2 near shortest

        graph = NX.Graph()  # new graph
        for i in shortest_idxs:
            take_edges = numpy.nonzero(labels == i)[0]
            this_cluster_directions = obs[take_edges][:, 0]
            this_cluster_distances = obs[take_edges][:, 1]
            median_cluster_direction = numpy.median(this_cluster_directions)
            median_cluster_distance = numpy.median(this_cluster_distances)
            ## print 'mean',numpy.mean(this_cluster_distances)
            ## print 'median',numpy.median(this_cluster_distances)
            ## print 'std',numpy.std(this_cluster_distances)
            ## print
            for j in take_edges:
                this_distance = obs[j, 1]
                this_direction = obs[j, 0]
                if this_distance >= distance_thresh * median_cluster_distance:
                    # too long - ignore
                    continue

                if not angles_near(this_direction, median_cluster_direction, angle_thresh, mod_pi=True):
                    # angle is too different
                    continue
                graph.add_edge(edges[j])

    return graph, nodes