def circles_of_hell(request, project_id=None): """ Given a set of one or more skeleton IDs, find all skeletons that connect them (n_circles=1), or that connect to others that connect them (n_circles=2), etc. Returns a list of unique skeleton IDs that exclude the ones provided as argument. """ n_circles = int(request.POST.get('n_circles', 1)) if n_circles < 1: raise Exception("Requires at least one circle.") first_circle = set(int(v) for k,v in request.POST.iteritems() if k.startswith('skeleton_ids[')) if not first_circle: raise Exception("No skeletons were provided.") cursor = connection.cursor() mins, _ = _clean_mins(request, cursor, int(project_id)) current_circle = first_circle all_circles = first_circle while n_circles > 0 and current_circle: n_circles -= 1 connections = _next_circle(current_circle, cursor) next_circle = set(skID for c in connections.itervalues() for relationID, cs in c.iteritems() for skID, count in cs.iteritems() if count >= mins[relationID]) current_circle = next_circle - all_circles all_circles = all_circles.union(next_circle) skeleton_ids = tuple(all_circles - first_circle) return HttpResponse(json.dumps([skeleton_ids, _neuronnames(skeleton_ids, project_id)]))
def circles_of_hell(request, project_id=None): """ Given a set of one or more skeleton IDs, find all skeletons that connect them (n_circles=1), or that connect to others that connect them (n_circles=2), etc. Returns a list of unique skeleton IDs that exclude the ones provided as argument. """ n_circles = int(request.POST.get('n_circles', 1)) if n_circles < 1: raise Exception("Requires at least one circle.") first_circle = set( int(v) for k, v in six.iteritems(request.POST) if k.startswith('skeleton_ids[')) if not first_circle: raise Exception("No skeletons were provided.") cursor = connection.cursor() mins, relations = _clean_mins(request, cursor, int(project_id)) current_circle = first_circle all_circles = first_circle while n_circles > 0 and current_circle: n_circles -= 1 connections = _next_circle(current_circle, relations, cursor) next_circle = set(skID for c in six.itervalues(connections) \ for relationID, cs in six.iteritems(c) \ for skID, count in six.iteritems(cs) if count >= mins[relationID]) current_circle = next_circle - all_circles all_circles = all_circles.union(next_circle) skeleton_ids = tuple(all_circles - first_circle) return JsonResponse( [skeleton_ids, _neuronnames(skeleton_ids, project_id)], safe=False)
def circles_of_hell(request: HttpRequest, project_id) -> JsonResponse: """ Given a set of one or more skeleton IDs, find all skeletons that connect them (n_circles=1), or that connect to others that connect them (n_circles=2), etc. Returns a list of unique skeleton IDs that exclude the ones provided as argument. --- parameters: - name: skeleton_ids[] description: IDs of the skeletons to start expanding from. required: true type: array items: type: integer paramType: form - name: n_circles description: (Optional) The numbers of recursive expansions. required: false defaultValue: 1 type: integer paramType: form - name: allowed_connector_ids[] description: (Optional) IDs of connector nodes that are allowed to be used for expansion. required: false type: array items: type: integer paramType: form """ n_circles = int(request.POST.get('n_circles', 1)) if n_circles < 1: raise Exception("Requires at least one circle.") first_circle = set( get_request_list(request.POST, 'skeleton_ids', map_fn=int)) if not first_circle: raise Exception("No skeletons were provided.") cursor = connection.cursor() mins, relations = _clean_mins(request, cursor, int(project_id)) allowed_connector_ids = get_request_list(request.POST, 'allowed_connector_ids', None) current_circle = first_circle all_circles = first_circle while n_circles > 0 and current_circle: n_circles -= 1 connections = _next_circle(current_circle, relations, cursor, allowed_connector_ids) next_circle = set(skID for c in connections.values() \ for relationID, cs in c.items() \ for skID, count in cs.items() if count >= mins[relationID]) current_circle = next_circle - all_circles all_circles = all_circles.union(next_circle) skeleton_ids = tuple(all_circles - first_circle) return JsonResponse( [skeleton_ids, _neuronnames(skeleton_ids, project_id)], safe=False)
def find_directed_paths(request, project_id=None): """ Given a set of two or more skeleton IDs, find directed paths of connected neurons between them, for a maximum inner path length as given (i.e. origin and destination not counted). A directed path means that all edges are of the same kind, e.g. presynaptic_to. """ sources = set( int(v) for k, v in request.POST.iteritems() if k.startswith('skeleton_ids[')) if len(sources) < 2: raise Exception('Need at least 2 skeleton IDs to find directed paths!') path_length = int(request.POST.get('n_circles', 1)) cursor = connection.cursor() mins, relations = _clean_mins(request, cursor, int(project_id)) presynaptic_to = relations['presynaptic_to'] graph = nx.DiGraph() next_sources = sources all_sources = sources length = path_length def rev_args(fn): def f(arg1, arg2): fn(arg2, arg1) return f # Create a graph by growing the sources while length > 0 and next_sources: length -= 1 next_circles = _next_circle(next_sources, cursor) next_sources = set() for skid1, c in next_circles.iteritems(): for relationID, targets in c.iteritems(): threshold = mins[relationID] add_edge = graph.add_edge if relationID == presynaptic_to else rev_args( graph.add_edge) for skid2, count in targets.iteritems(): if count < threshold: continue add_edge(skid1, skid2) next_sources.add(skid2) next_sources = next_sources - all_sources all_sources = all_sources.union(next_sources) # Find all directed paths between all pairs of inputs unique = set() for start, end in combinations(sources, 2): for paths in [ nx.all_simple_paths(graph, start, end, path_length + 1), nx.all_simple_paths(graph, end, start, path_length + 1) ]: for path in paths: for node in path: unique.add(node) skeleton_ids = tuple(unique - sources) return HttpResponse( json.dumps([skeleton_ids, _neuronnames(skeleton_ids, project_id)]))
def find_directed_paths(request, project_id=None): """ Given a set of two or more skeleton IDs, find directed paths of connected neurons between them, for a maximum inner path length as given (i.e. origin and destination not counted). A directed path means that all edges are of the same kind, e.g. presynaptic_to. """ sources = set(int(v) for k,v in request.POST.iteritems() if k.startswith('skeleton_ids[')) if len(sources) < 2: raise Exception('Need at least 2 skeleton IDs to find directed paths!') path_length = int(request.POST.get('n_circles', 1)) cursor = connection.cursor() mins, relations = _clean_mins(request, cursor, int(project_id)) presynaptic_to = relations['presynaptic_to'] graph = nx.DiGraph() next_sources = sources all_sources = sources length = path_length def rev_args(fn): def f(arg1, arg2): fn(arg2, arg1) return f # Create a graph by growing the sources while length > 0 and next_sources: length -= 1 next_circles = _next_circle(next_sources, cursor) next_sources = set() for skid1, c in next_circles.iteritems(): for relationID, targets in c.iteritems(): threshold = mins[relationID] add_edge = graph.add_edge if relationID == presynaptic_to else rev_args(graph.add_edge) for skid2, count in targets.iteritems(): if count < threshold: continue add_edge(skid1, skid2) next_sources.add(skid2) next_sources = next_sources - all_sources all_sources = all_sources.union(next_sources) # Find all directed paths between all pairs of inputs unique = set() for start, end in combinations(sources, 2): for paths in [nx.all_simple_paths(graph, start, end, path_length + 1), nx.all_simple_paths(graph, end, start, path_length + 1)]: for path in paths: for node in path: unique.add(node) skeleton_ids = tuple(unique - sources) return HttpResponse(json.dumps([skeleton_ids, _neuronnames(skeleton_ids, project_id)]))