Ejemplo n.º 1
0
def split_by_synapse_domain(bandwidth, locations, arbors, treenode_connector, minis):
    """ locations: dictionary of treenode ID vs tuple with x,y,z
        arbors: dictionary of skeleton ID vs list of DiGraph (that were, or not, split by confidence)
        treenode_connectors: dictionary of treenode ID vs list of tuples of connector_id, string of 'presynaptic_to' or 'postsynaptic_to'
    """
    arbors2 = {} # Some arbors will be split further
    for skeleton_id, graphs in arbors.iteritems():
        subdomains = []
        arbors2[skeleton_id] = subdomains
        for graph in graphs:
            treenode_ids = []
            connector_ids =[]
            relation_ids = []
            for treenode_id in ifilter(treenode_connector.has_key, graph.nodes()):
                for c in treenode_connector.get(treenode_id):
                    connector_id, relation = c
                    treenode_ids.append(treenode_id)
                    connector_ids.append(connector_id)
                    relation_ids.append(relation)

            if not connector_ids:
                subdomains.append(graph)
                continue

            for parent_id, treenode_id in graph.edges():
                loc0 = locations[treenode_id]
                loc1 = locations[parent_id]
                graph[parent_id][treenode_id]['weight'] = norm(subtract(loc0, loc1))

            # Invoke Casey's magic
            synapse_group = tree_max_density(graph.to_undirected(), treenode_ids, connector_ids, relation_ids, [bandwidth]).values()[0]
            # The list of nodes of each synapse_group contains only nodes that have connectors
            # A local_max is the skeleton node most central to a synapse_group
            anchors = {}
            for domain in synapse_group.values():
                g = nx.DiGraph()
                g.add_nodes_from(domain.node_ids) # bogus graph, containing treenodes that point to connectors
                subdomains.append(g)
                anchors[domain.local_max] = g
            # Define edges between domains: create a simplified graph
            mini = simplify(graph, anchors.keys())
            # Replace each node by the corresponding graph, or a graph of a single node
            table = {}
            for node in mini.nodes():
                g = anchors.get(node)
                if not g:
                    # A branch node that was not an anchor, i.e. did not represent a synapse group
                    g = nx.Graph()
                    g.add_node(node, {'branch': True})
                    subdomains.append(g)
                # Associate the Graph with treenodes that have connectors
                # with the node in the minified tree
                mini.node[node]['g'] = g
            # Put the mini into a map of skeleton_id and list of minis,
            # to be used later for defining intra-neuron edges in the circuit graph
            minis[skeleton_id].append(mini)

    return arbors2, minis
Ejemplo n.º 2
0
def split_by_both(skeleton_id, digraph, locations, bandwidth, cs, connectors, intraedges):
    """ Split by confidence and synapse domain. Populates connectors and intraedges (side effects). """
    nodes = []
    branch_nodes = []

    chunks, chunkIDs = subgraphs(digraph, skeleton_id)

    for i, chunkID, chunk in izip(count(start=1), chunkIDs, chunks):
        # Populate edge properties with the weight
        for parent, child in chunk.edges_iter():
            chunk[parent][child]['weight'] = norm(subtract(locations[child], locations[parent]))

        # Check if need to expand at all
        blob = tuple(c for c in cs if c[0] in chunk)
        if 0 == len(blob):
            nodes.append(chunkID)
            continue

        treenode_ids, connector_ids, relation_ids = zip(*blob)

        if 0 == len(connector_ids):
            nodes.append(chunkID)
            continue

        # Invoke Casey's magic: split by synapse domain
        domains = tree_max_density(chunk.to_undirected(), treenode_ids, connector_ids, relation_ids, [bandwidth]).values()[0]

        # domains is a dictionary of index vs SynapseGroup instance

        if 1 == len(domains):
            for connector_id, relation_id in izip(connector_ids, relation_ids):
                connectors[connector_id][relation_id].append(chunkID)
            nodes.append(chunkID)
            continue

        # Create edges between domains
        # Pick one treenode from each domain to act as anchor
        anchors = {d.node_ids[0]: (i+k, d) for k, d in domains.iteritems()}

        # Create new Graph where the edges are the edges among synapse domains
        mini = simplify(chunk, anchors.iterkeys())

        # Many side effects:
        # * add internal edges to intraedges
        # * add each domain to nodes
        # * custom-apply populate_connectors with the known synapses of each domain
        #   (rather than having to sift through all in cs)
        mini_nodes = {}
        for node in mini.nodes_iter():
            blob = anchors.get(node, None)
            if blob:
                index, domain = blob
                domainID = '%s_%s' % (chunkID, index)
                nodes.append(domainID)
                for connector_id, relation_id in izip(domain.connector_ids, domain.relations):
                    connectors[connector_id][relation_id].append(domainID)
            else:
                domainID = '%s_%s' % (chunkID, node)
                branch_nodes.append(domainID)
            mini_nodes[node] = domainID

        for a1, a2 in mini.edges_iter():
            intraedges.append((mini_nodes[a1], mini_nodes[a2]))

    return nodes, branch_nodes