예제 #1
0
파일: treenode.py 프로젝트: pgunn/CATMAID
def create_treenode(request, project_id=None):
    """
    Add a new treenode to the database
    ----------------------------------

    1. Add new treenode for a given skeleton id. Parent should not be empty.
       return: new treenode id
       If the parent's skeleton has a single node and belongs to the
       'Isolated synaptic terminals' group, then reassign ownership
       of the skeleton and the neuron to the user. The treenode remains
       property of the original user who created it.

    2. Add new treenode (root) and create a new skeleton (maybe for a given
       neuron) return: new treenode id and skeleton id.

    If a neuron id is given, use that one to create the skeleton as a model of
    it.
    """

    params = {}
    float_values = {'x': 0, 'y': 0, 'z': 0, 'radius': 0}
    int_values = {'confidence': 0, 'useneuron': -1, 'parent_id': -1}
    string_values = {}
    for p in float_values.keys():
        params[p] = float(request.POST.get(p, float_values[p]))
    for p in int_values.keys():
        params[p] = int(request.POST.get(p, int_values[p]))
    for p in string_values.keys():
        params[p] = request.POST.get(p, string_values[p])

    # Get optional initial links to connectors, expect each entry to be a list
    # of connector ID, relation ID and confidence.
    links = get_request_list(request.POST, 'links', [], map_fn=int)

    # Make sure the back-end is in the expected state if the node should have a
    # parent and will therefore become part of another skeleton.
    parent_id = int(params['parent_id'])
    has_parent = parent_id and parent_id != -1
    if has_parent:
        state.validate_state(parent_id,
                             request.POST.get('state'),
                             parent_edittime=has_parent,
                             lock=True)

    new_treenode = _create_treenode(project_id,
                                    request.user,
                                    request.user,
                                    params['x'],
                                    params['y'],
                                    params['z'],
                                    params['radius'],
                                    params['confidence'],
                                    params['useneuron'],
                                    params['parent_id'],
                                    neuron_name=request.POST.get(
                                        'neuron_name', None))

    # Create all initial links
    if links:
        created_links = create_connector_link(project_id, request.user.id,
                                              new_treenode.treenode_id,
                                              new_treenode.skeleton_id, links)
    else:
        created_links = []

    return JsonResponse({
        'treenode_id': new_treenode.treenode_id,
        'skeleton_id': new_treenode.skeleton_id,
        'edition_time': new_treenode.edition_time,
        'parent_edition_time': new_treenode.parent_edition_time,
        'created_links': created_links
    })
예제 #2
0
파일: treenode.py 프로젝트: pgunn/CATMAID
def insert_treenode(request, project_id=None):
    """
    Create a new treenode between two existing nodes. Its creator and
    creation_date information will be set to information of child node. No node
    will be created, if the node on the edge between the given child and parent
    node.
    """
    # Use creation time, if part of parameter set
    params = {}
    float_values = {'x': 0, 'y': 0, 'z': 0, 'radius': 0}
    int_values = {'confidence': 0, 'parent_id': -1, 'child_id': -1}
    for p in float_values.keys():
        params[p] = float(request.POST.get(p, float_values[p]))
    for p in int_values.keys():
        params[p] = int(request.POST.get(p, int_values[p]))

    # If siblings should be taken over, all children of the parent node will be
    # come children of the inserted node. This requires extra state
    # information: the child state for the paren.
    takeover_child_ids = get_request_list(request.POST, 'takeover_child_ids',
                                          None, int)

    # Get optional initial links to connectors, expect each entry to be a list
    # of connector ID and relation ID.
    try:
        links = get_request_list(request.POST, 'links', [], int)
    except Exception as e:
        raise ValueError("Couldn't parse list parameter: {}".format(e))

    # Make sure the back-end is in the expected state if the node should have a
    # parent and will therefore become part of another skeleton.
    parent_id = params.get('parent_id')
    child_id = params.get('child_id')
    if parent_id not in (-1, None):
        s = request.POST.get('state')
        # Testing egular edge insertion is assumed if a child ID is provided
        partial_child_checks = [] if child_id in (-1, None) else [child_id]
        if takeover_child_ids:
            partial_child_checks.extend(takeover_child_ids)
        state.validate_state(parent_id,
                             s,
                             node=True,
                             children=partial_child_checks or False,
                             lock=True),

    # Find child and parent of new treenode
    child = Treenode.objects.get(pk=params['child_id'])
    parent = Treenode.objects.get(pk=params['parent_id'])

    # Make sure both nodes are actually child and parent
    if not child.parent == parent:
        raise ValueError('The provided nodes need to be child and parent')

    # Make sure the requested location for the new node is on the edge between
    # both existing nodes if the user has no edit permissions on the neuron.
    try:
        can_edit_treenode_or_fail(request.user, project_id, parent.id)
        user, time = request.user, None
    except:
        child_loc = Point3D(child.location_x, child.location_y,
                            child.location_z)
        parent_loc = Point3D(parent.location_x, parent.location_y,
                             parent.location_z)
        new_node_loc = Point3D(params['x'], params['y'], params['z'])
        if not is_collinear(child_loc, parent_loc, new_node_loc, True, 0.001):
            raise ValueError(
                'New node location has to be between child and parent')

        # Use creator and creation time for neighboring node that was created last.
        if child.creation_time < parent.creation_time:
            user, time = parent.user, parent.creation_time
        else:
            user, time = child.user, child.creation_time

    # Create new treenode
    new_treenode = _create_treenode(project_id, user, request.user,
                                    params['x'], params['y'], params['z'],
                                    params['radius'], params['confidence'], -1,
                                    params['parent_id'], time)

    # Update parent of child to new treenode, do this in raw SQL to also get the
    # updated edition time Update also takeover children
    cursor = connection.cursor()
    params = [new_treenode.treenode_id, child.id]
    if takeover_child_ids:
        params.extend(takeover_child_ids)
        child_template = ",".join(("%s", ) * (len(takeover_child_ids) + 1))
    else:
        child_template = "%s"

    cursor.execute(
        """
        UPDATE treenode SET parent_id = %s
         WHERE id IN ({})
     RETURNING id, edition_time
    """.format(child_template), params)
    result = cursor.fetchall()
    if not result or (len(params) - 1) != len(result):
        raise ValueError("Couldn't update parent of inserted node's child: " +
                         child.id)
    child_edition_times = [[k, v] for k, v in result]

    # Create all initial links
    if links:
        created_links = create_connector_link(project_id, request.user.id,
                                              new_treenode.treenode_id,
                                              new_treenode.skeleton_id, links)
    else:
        created_links = []

    return JsonResponse({
        'treenode_id': new_treenode.treenode_id,
        'skeleton_id': new_treenode.skeleton_id,
        'edition_time': new_treenode.edition_time,
        'parent_edition_time': new_treenode.parent_edition_time,
        'child_edition_times': child_edition_times,
        'created_links': created_links
    })
예제 #3
0
파일: treenode.py 프로젝트: catmaid/CATMAID
def create_treenode(request, project_id=None):
    """
    Add a new treenode to the database
    ----------------------------------

    1. Add new treenode for a given skeleton id. Parent should not be empty.
       return: new treenode id
       If the parent's skeleton has a single node and belongs to the
       'Isolated synaptic terminals' group, then reassign ownership
       of the skeleton and the neuron to the user. The treenode remains
       property of the original user who created it.

    2. Add new treenode (root) and create a new skeleton (maybe for a given
       neuron) return: new treenode id and skeleton id.

    If a neuron id is given, use that one to create the skeleton as a model of
    it.
    """

    params = {}
    float_values = {
            'x': 0,
            'y': 0,
            'z': 0,
            'radius': 0}
    int_values = {
            'confidence': 0,
            'useneuron': -1,
            'parent_id': -1}
    string_values = {}
    for p in float_values.keys():
        params[p] = float(request.POST.get(p, float_values[p]))
    for p in int_values.keys():
        params[p] = int(request.POST.get(p, int_values[p]))
    for p in string_values.keys():
        params[p] = request.POST.get(p, string_values[p])

    # Get optional initial links to connectors, expect each entry to be a list
    # of connector ID, relation ID and confidence.
    links = get_request_list(request.POST, 'links', [], map_fn=int)

    # Make sure the back-end is in the expected state if the node should have a
    # parent and will therefore become part of another skeleton.
    parent_id = int(params['parent_id'])
    has_parent = parent_id and parent_id != -1
    if has_parent:
        state.validate_state(parent_id, request.POST.get('state'),
                parent_edittime=has_parent, lock=True)

    new_treenode = _create_treenode(project_id, request.user, request.user,
            params['x'], params['y'], params['z'], params['radius'],
            params['confidence'], params['useneuron'], params['parent_id'],
            neuron_name=request.POST.get('neuron_name', None))

    # Create all initial links
    if links:
        created_links = create_connector_link(project_id, request.user.id,
                new_treenode.treenode_id, new_treenode.skeleton_id, links)
    else:
        created_links = []

    return JsonResponse({
        'treenode_id': new_treenode.treenode_id,
        'skeleton_id': new_treenode.skeleton_id,
        'edition_time': new_treenode.edition_time,
        'parent_edition_time': new_treenode.parent_edition_time,
        'created_links': created_links
    })
예제 #4
0
파일: treenode.py 프로젝트: catmaid/CATMAID
def insert_treenode(request, project_id=None):
    """
    Create a new treenode between two existing nodes. Its creator and
    creation_date information will be set to information of child node. No node
    will be created, if the node on the edge between the given child and parent
    node.
    """
    # Use creation time, if part of parameter set
    params = {}
    float_values = {
        'x': 0,
        'y': 0,
        'z': 0,
        'radius': 0
    }
    int_values = {
        'confidence': 0,
        'parent_id': -1,
        'child_id': -1
    }
    for p in float_values.keys():
        params[p] = float(request.POST.get(p, float_values[p]))
    for p in int_values.keys():
        params[p] = int(request.POST.get(p, int_values[p]))

    # If siblings should be taken over, all children of the parent node will be
    # come children of the inserted node. This requires extra state
    # information: the child state for the paren.
    takeover_child_ids = get_request_list(request.POST,
            'takeover_child_ids', None, int)

    # Get optional initial links to connectors, expect each entry to be a list
    # of connector ID and relation ID.
    try:
        links = get_request_list(request.POST, 'links', [], int)
    except Exception as e:
        raise ValueError("Couldn't parse list parameter: {}".format(e))

    # Make sure the back-end is in the expected state if the node should have a
    # parent and will therefore become part of another skeleton.
    parent_id = params.get('parent_id')
    child_id = params.get('child_id')
    if parent_id not in (-1, None):
        s = request.POST.get('state')
        # Testing egular edge insertion is assumed if a child ID is provided
        partial_child_checks = [] if child_id in (-1, None) else [child_id]
        if takeover_child_ids:
            partial_child_checks.extend(takeover_child_ids)
        state.validate_state(parent_id, s, node=True,
                children=partial_child_checks or False, lock=True),

    # Find child and parent of new treenode
    child = Treenode.objects.get(pk=params['child_id'])
    parent = Treenode.objects.get(pk=params['parent_id'])

    # Make sure both nodes are actually child and parent
    if not child.parent == parent:
        raise ValueError('The provided nodes need to be child and parent')

    # Make sure the requested location for the new node is on the edge between
    # both existing nodes if the user has no edit permissions on the neuron.
    try:
        can_edit_treenode_or_fail(request.user, project_id, parent.id)
        user, time = request.user, None
    except:
        child_loc = Point3D(child.location_x, child.location_y, child.location_z)
        parent_loc = Point3D(parent.location_x, parent.location_y, parent.location_z)
        new_node_loc = Point3D(params['x'], params['y'], params['z'])
        if not is_collinear(child_loc, parent_loc, new_node_loc, True, 0.001):
            raise ValueError('New node location has to be between child and parent')

        # Use creator and creation time for neighboring node that was created last.
        if child.creation_time < parent.creation_time:
            user, time = parent.user, parent.creation_time
        else:
            user, time = child.user, child.creation_time

    # Create new treenode
    new_treenode = _create_treenode(project_id,
            user, request.user, params['x'], params['y'], params['z'],
            params['radius'], params['confidence'], -1, params['parent_id'], time)

    # Update parent of child to new treenode, do this in raw SQL to also get the
    # updated edition time Update also takeover children
    cursor = connection.cursor()
    params = [new_treenode.treenode_id, child.id]
    if takeover_child_ids:
        params.extend(takeover_child_ids)
        child_template = ",".join(("%s",) * (len(takeover_child_ids) + 1))
    else:
        child_template = "%s"

    cursor.execute("""
        UPDATE treenode SET parent_id = %s
         WHERE id IN ({})
     RETURNING id, edition_time
    """.format(child_template), params)
    result = cursor.fetchall()
    if not result or (len(params) - 1) != len(result):
        raise ValueError("Couldn't update parent of inserted node's child: " + child.id)
    child_edition_times = [[k,v] for k,v in result]

    # Create all initial links
    if links:
        created_links = create_connector_link(project_id, request.user.id,
                new_treenode.treenode_id, new_treenode.skeleton_id, links)
    else:
        created_links = []

    return JsonResponse({
        'treenode_id': new_treenode.treenode_id,
        'skeleton_id': new_treenode.skeleton_id,
        'edition_time': new_treenode.edition_time,
        'parent_edition_time': new_treenode.parent_edition_time,
        'child_edition_times': child_edition_times,
        'created_links': created_links
    })
예제 #5
0
    cursor.execute(
        """
        UPDATE treenode SET parent_id = %s
         WHERE id IN ({})
     RETURNING id, edition_time
    """.format(child_template), params)
    result = cursor.fetchall()
    if not result or (len(params) - 1) != len(result):
        raise ValueError("Couldn't update parent of inserted node's child: " +
                         child.id)
    child_edition_times = [[k, v] for k, v in result]

    # Create all initial links
    if links:
        created_links = create_connector_link(project_id, request.user.id,
                                              new_treenode.treenode_id,
                                              new_treenode.skeleton_id, links)
    else:
        created_links = []

    return JsonResponse({
        'treenode_id': new_treenode.treenode_id,
        'skeleton_id': new_treenode.skeleton_id,
        'edition_time': new_treenode.edition_time,
        'parent_edition_time': new_treenode.parent_edition_time,
        'child_edition_times': child_edition_times,
        'created_links': created_links
    })


class NewTreenode(object):
예제 #6
0
    else:
        child_template = "%s"

    cursor.execute("""
        UPDATE treenode SET parent_id = %s
         WHERE id IN ({})
     RETURNING id, edition_time
    """.format(child_template), params)
    result = cursor.fetchall()
    if not result or (len(params) - 1) != len(result):
        raise ValueError("Couldn't update parent of inserted node's child: " + child.id)
    child_edition_times = [[k,v] for k,v in result]

    # Create all initial links
    if links:
        created_links = create_connector_link(project_id, request.user.id,
                new_treenode.treenode_id, new_treenode.skeleton_id, links);
    else:
        created_links = []

    return JsonResponse({
        'treenode_id': new_treenode.treenode_id,
        'skeleton_id': new_treenode.skeleton_id,
        'edition_time': new_treenode.edition_time,
        'parent_edition_time': new_treenode.parent_edition_time,
        'child_edition_times': child_edition_times,
        'created_links': created_links
    })

class NewTreenode(object):
    """Represent a newly created treenode and all the information that is
    returned to the client