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
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
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
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 six.iteritems(arbors): 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(six.itervalues(max_density)) # 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 six.itervalues(synapse_group): 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