Example #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.items():
        subdomains = []
        arbors2[skeleton_id] = subdomains
        for graph in graphs:
            treenode_ids = []
            connector_ids =[]
            relation_ids = []
            for treenode_id in filter(treenode_connector.has_key, graph.nodes_iter()):
                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_iter():
                loc0 = locations[treenode_id]
                loc1 = locations[parent_id]
                graph[parent_id][treenode_id]['weight'] = norm(subtract(loc0, loc1))

            # Invoke Casey's magic
            max_density = tree_max_density(graph.to_undirected(), treenode_ids,
                    connector_ids, relation_ids, [bandwidth])
            synapse_group = next(max_density.values())
            # 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
            for node in mini.nodes_iter():
                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
Example #2
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_iter()):
                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_iter():
                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.itervalues():
                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
            for node in mini.nodes_iter():
                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
Example #3
0
def split_by_both(skeleton_id, digraph, locations, bandwidth, cs, connectors, intraedges) -> Tuple[List, List]:
    """ 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 zip(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) # type: Optional[Tuple]
                                                     # the two different uses of blob in this context
                                                     # (other being in for node in mini.nodes_iter() below )
                                                     # makes typing difficult and may be a maintenance concern
        if 0 == len(blob): # type: ignore
            nodes.append(chunkID)
            continue

        treenode_ids, connector_ids, relation_ids, confidences = list(zip(*blob)) # type: ignore

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

        # Invoke Casey's magic: split by synapse domain
        max_density = tree_max_density(chunk.to_undirected(), treenode_ids,
                connector_ids, relation_ids, [bandwidth])
        # Get first element of max_density
        domains = next(iter(max_density.values()))

        # domains is a dictionary of index vs SynapseGroup instance

        if 1 == len(domains):
            for connector_id, relation_id, confidence in zip(connector_ids, relation_ids, confidences):
                connectors[connector_id][relation_id].append((chunkID, confidence))
            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.items()}

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

        # 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)
            if blob:
                index, domain = blob
                domainID = '%s_%s' % (chunkID, index)
                nodes.append(domainID)
                for connector_id, relation_id in zip(domain.connector_ids, domain.relations):
                    confidence = confidences[connector_ids.index(connector_id)]
                    connectors[connector_id][relation_id].append((domainID, confidence))
            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
Example #4
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 zip(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, confidences = list(zip(*blob))

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

        # Invoke Casey's magic: split by synapse domain
        max_density = tree_max_density(chunk.to_undirected(), treenode_ids,
                connector_ids, relation_ids, [bandwidth])
        # Get first element of max_density
        domains = next(iter(max_density.values()))

        # domains is a dictionary of index vs SynapseGroup instance

        if 1 == len(domains):
            for connector_id, relation_id, confidence in zip(connector_ids, relation_ids, confidences):
                connectors[connector_id][relation_id].append((chunkID, confidence))
            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.items()}

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

        # 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 zip(domain.connector_ids, domain.relations):
                    confidence = confidences[connector_ids.index(connector_id)]
                    connectors[connector_id][relation_id].append((domainID, confidence))
            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