示例#1
0
    def test_is_collinear_big_numbers(self):
        from catmaid.util import Point3D, is_collinear

        p1 = Point3D(-299924.0, 505016.0, 40.0)
        p2 = Point3D(-319905.0, 505904.0, 40.0)
        p3 = Point3D(-309915.0, 505460.0, 40.0)

        self.assertTrue(is_collinear(p1, p2, p3))
        self.assertTrue(is_collinear(p1, p2, p3, True))
示例#2
0
    def test_is_collinear_diagonal(self):
        from catmaid.util import Point3D, is_collinear

        p1 = Point3D(-1.0, 1.0, 1.0)
        p2 = Point3D(1.0, 2.0, 3.0)
        p3 = Point3D(-2.0, 0.5, 0.0)

        self.assertTrue(is_collinear(p1, p2, p3))
        self.assertFalse(is_collinear(p1, p2, p3, True))
示例#3
0
    def test_is_collinear_on_z_axis(self):
        from catmaid.util import Point3D, is_collinear

        p1 = Point3D(0.0, 0.0, 0.0)
        p2 = Point3D(0.0, 0.0, 1.0)
        p3 = Point3D(0.0, 0.0, 1.5)

        self.assertTrue(is_collinear(p1, p2, p3))
        self.assertFalse(is_collinear(p1, p2, p3, True))
示例#4
0
    def test_is_collinear_precision(self):
        from catmaid.util import Point3D, is_collinear

        p1 = Point3D(0.0, 0.0, 0.0)
        p2 = Point3D(1.0, 0.001, 0.0)
        p3 = Point3D(1.5, 0.0, 0.0)

        self.assertTrue(is_collinear(p1, p2, p3))
        self.assertFalse(is_collinear(p1, p2, p3, True))
示例#5
0
    def test_is_collinear_big_numbers(self):
        from catmaid.util import Point3D, is_collinear

        p1 = Point3D(-299924.0, 505016.0, 40.0)
        p2 = Point3D(-319905.0, 505904.0, 40.0)
        p3 = Point3D(-309915.0, 505460.0, 40.0)

        self.assertTrue(is_collinear(p1, p2, p3))
        self.assertTrue(is_collinear(p1, p2, p3, True))
示例#6
0
    def test_is_collinear_precision(self):
        from catmaid.util import Point3D, is_collinear

        p1 = Point3D(0.0, 0.0, 0.0)
        p2 = Point3D(1.0, 0.001, 0.0)
        p3 = Point3D(1.5, 0.0, 0.0)

        self.assertTrue(is_collinear(p1, p2, p3))
        self.assertFalse(is_collinear(p1, p2, p3, True))
示例#7
0
    def test_is_collinear_diagonal(self):
        from catmaid.util import Point3D, is_collinear

        p1 = Point3D(-1.0, 1.0, 1.0)
        p2 = Point3D(1.0, 2.0, 3.0)
        p3 = Point3D(-2.0, 0.5, 0.0)

        self.assertTrue(is_collinear(p1, p2, p3))
        self.assertFalse(is_collinear(p1, p2, p3, True))
示例#8
0
    def test_is_collinear_on_z_axis(self):
        from catmaid.util import Point3D, is_collinear

        p1 = Point3D(0.0, 0.0, 0.0)
        p2 = Point3D(0.0, 0.0, 1.0)
        p3 = Point3D(0.0, 0.0, 1.5)

        self.assertTrue(is_collinear(p1, p2, p3))
        self.assertFalse(is_collinear(p1, p2, p3, True))
示例#9
0
文件: sampler.py 项目: msayr/CATMAID
    def link_added_node(data, new_nodes):
        # The target node has to be a new node
        n = new_nodes[data[0]]
        # Find child and parent of new treenode. Check first if they have been
        # created as newly as well.
        child = new_nodes.get(data[1])
        if not child:
            child = Treenode.objects.get(pk=data[1])
        parent = new_nodes.get(data[2])
        if not parent:
            parent = Treenode.objects.get(pk=data[2])

        # 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')

        x, y, z = n.location_x, n.location_y, n.location_z
        new_node_loc = Point3D(x, y, z)
        child_loc = Point3D(child.location_x, child.location_y,
                            child.location_z)
        parent_loc = Point3D(parent.location_x, parent.location_y,
                             parent.location_z)

        if not is_collinear(child_loc, parent_loc, new_node_loc, True,
                            epsilon):
            raise ValueError(
                'New node location has to be collinear with child ' +
                f'and parent. Child: {child_loc}, New Node: {new_node_loc}, Parent: {parent_loc}'
            )

        # Tag new treenode with SAMPLER_CREATED_CLASS
        label, _ = ClassInstance.objects.get_or_create(
            project_id=project_id,
            name=SAMPLER_CREATED_CLASS,
            class_column=label_class,
            defaults={'user': request.user})
        TreenodeClassInstance.objects.create(project_id=project_id,
                                             user=request.user,
                                             relation=labeled_as,
                                             treenode=n,
                                             class_instance=label)

        # Update child node. Reviews don't need to be updated, because they are
        # only reset of a node's location changes.
        child.parent_id = n.id
        child.save()
示例#10
0
文件: sampler.py 项目: tomka/CATMAID
    def link_added_node(data, new_nodes):
        # The target node has to be a new node
        n = new_nodes[data[0]]
        # Find child and parent of new treenode. Check first if they have been
        # created as newly as well.
        child = new_nodes.get(data[1])
        if not child:
            child = Treenode.objects.get(pk=data[1])
        parent = new_nodes.get(data[2])
        if not parent:
            parent = Treenode.objects.get(pk=data[2])

        # 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')

        x, y, z = n.location_x, n.location_y, n.location_z
        new_node_loc = Point3D(x, y, z)
        child_loc = Point3D(child.location_x, child.location_y, child.location_z)
        parent_loc = Point3D(parent.location_x, parent.location_y, parent.location_z)

        if not is_collinear(child_loc, parent_loc, new_node_loc, True, epsilon):
            raise ValueError('New node location has to be collinear with child and parent')

        # Tag new treenode with SAMPLER_CREATED_CLASS
        label, _ = ClassInstance.objects.get_or_create(project_id=project_id,
                name=SAMPLER_CREATED_CLASS, class_column=label_class, defaults={
                    'user': request.user
                })
        TreenodeClassInstance.objects.create(project_id=project_id,
                user=request.user, relation=labeled_as, treenode=n,
                class_instance=label)

        # Update child node. Reviews don't need to be updated, because they are
        # only reset of a node's location changes.
        child.parent_id = n.id
        child.save()
示例#11
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
    })
示例#12
0
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
    })
示例#13
0
def delete_sampler(request, project_id, sampler_id):
    """Delete a sampler if permissions allow it.

    If the sampler was created with allowing the creation of new boundary nodes,
    these nodes are removed by default if they have not been modified since
    their insertion. This can optionally be disabled using the
    <delete_created_nodes> parameter.
    ---
    parameters:
     - name: delete_created_nodes
       description: |
         Optional flag to disable automatic removal of untouched
         nodes created for this sampler's intervals.
       type: boolean
       default: true
       paramType: form
       required: false
    """
    can_edit_or_fail(request.user, sampler_id, "catmaid_sampler")
    sampler = Sampler.objects.get(id=sampler_id)

    n_deleted_nodes = 0
    delete_created_nodes = get_request_bool(request.POST, 'delete_created_nodes', True)
    if delete_created_nodes and sampler.create_interval_boundaries:
        labeled_as_relation = Relation.objects.get(project=project_id, relation_name='labeled_as')
        label_class = Class.objects.get(project=project_id, class_name='label')
        label_class_instance = ClassInstance.objects.get(project=project_id,
                class_column=label_class, name=SAMPLER_CREATED_CLASS)
        # If the sampler was parameterized to created interval boundary nodes,
        # these nodes can now be removed if they are still collinear with their
        # child and parent node and have not been touched. These nodes are all
        # nodes that are referenced by intervals of this sampler that have the
        # SAMPLER_CREATED_CLASS tag with their creation time being the same as the
        # edition time. Such nodes can only be sampler interval start/end nodes.
        params = {
            'project_id': project_id,
            'sampler_id': sampler_id,
            'labeled_as_rel': labeled_as_relation.id,
            'label_class': label_class.id,
            'label_class_instance': label_class_instance.id
        }
        cursor = connection.cursor()

        # Get all created sampler interval boundary treenodes that have been
        # created during sampler creation. The result will also contain parent
        # and child locations. We need to set extra_float_digits to get enough
        # precision for the location data to do a collinearity test.
        cursor.execute("""
            SET extra_float_digits = 3;

            WITH sampler_treenode AS (
                -- Get all treenodes linked to intervals of this sampler. Only
                -- select those nodes that are referenced by no other sampler
                -- (using an anti join).
                SELECT DISTINCT all_added_nodes.id
                FROM (
                    SELECT DISTINCT UNNEST(ARRAY[i.start_node_id, i.end_node_id]) AS id
                    FROM catmaid_samplerinterval i
                    JOIN catmaid_samplerdomain d
                        ON i.domain_id = d.id
                    WHERE d.sampler_id = %(sampler_id)s
                ) all_added_nodes
                JOIN catmaid_samplerinterval csi
                    ON csi.start_node_id = all_added_nodes.id
                    OR csi.end_node_id = all_added_nodes.id
                JOIN catmaid_samplerdomain csd
                    ON csd.id = csi.domain_id
                GROUP BY all_added_nodes.id
                HAVING COUNT(DISTINCT csd.sampler_id) = 1
            ), sampler_created_treenode AS (
                -- Find all treenodes that were created by the sampler and are
                -- undmodified.
                SELECT st.id
                FROM sampler_treenode st
                JOIN treenode_class_instance tci
                    ON st.id = tci.treenode_id
                WHERE tci.relation_id = %(labeled_as_rel)s
                AND tci.class_instance_id = %(label_class_instance)s
            )
            SELECT
                t.id, t.location_x, t.location_y, t.location_z,
                c.id, c.location_x, c.location_y, c.location_z,
                p.id, p.location_x, p.location_y, p.location_z
            FROM (
                -- Make sure we look only at nodes that don't have multiple nodes.
                SELECT st.id
                FROM treenode tt
                JOIN sampler_created_treenode st
                    ON tt.parent_id = st.id
                GROUP BY st.id
                HAVING count(*) = 1

            ) non_branch_treenodes(id)
            JOIN treenode t
                ON t.id = non_branch_treenodes.id
            JOIN treenode p
                ON p.id = t.parent_id
            JOIN treenode c
                ON c.parent_id = t.id
            WHERE t.project_id = %(project_id)s;
        """, params)

        created_treenodes = [r for r in cursor.fetchall()]

        if created_treenodes:
            added_node_index = dict((n[0], n) for n in created_treenodes)
            # Find those created treenodes that are collinear with their parent and
            # child node. If they are, remove those nodes. Ideally, we would move
            # the collinearity test into SQL as well.
            nodes_to_remove = []
            parents_to_fix = []
            child, node, parent = Point3D(0, 0, 0), Point3D(0, 0, 0), Point3D(0, 0, 0)
            for n in created_treenodes:
                n_id, node.x, node.y, node.z = n[0], n[1], n[2], n[3]
                c_id, child.x, child.y, child.z = n[4], n[5], n[6], n[7]
                p_id, parent.x, parent.y, parent.z = n[8], n[9], n[10], n[11]

                child_is_original_node = c_id not in added_node_index
                if is_collinear(child, parent, node, True, 1.0):
                    nodes_to_remove.append(n_id)
                    # Only update nodes that don't get deleted anyway
                    if child_is_original_node:
                        parents_to_fix.append((c_id, p_id))
                else:
                    parents_to_fix.append((n_id, p_id))

            # Update parent in formation in parent relation updates. If present
            # parent IDs point to a removed node, the next real parent will be
            # used instead.
            parent_update = []
            for n, (c_id, p_id) in enumerate(parents_to_fix):
                parent_is_persistent = p_id not in added_node_index
                if parent_is_persistent:
                    parent_update.append((c_id, p_id))
                else:
                    # Find next existing node upstream
                    new_parent_id = p_id
                    while not parent_is_persistent:
                        parent_is_persistent = new_parent_id not in nodes_to_remove
                        node_data = added_node_index.get(new_parent_id)
                        # An added node would be used if it is not removed, e.g.
                        # du to not being collinear anymore.
                        if node_data and not parent_is_persistent:
                            new_parent_id = node_data[8]
                        else:
                            parent_update.append((c_id, new_parent_id))

            if nodes_to_remove:
                query_parts = []
                params = []
                if parent_update:
                    update_nodes_template = ",".join("(%s, %s)" for _ in parent_update)
                    update_nodes_flattened = list(chain.from_iterable(parent_update))
                    query_parts.append("""
                        UPDATE treenode
                        SET parent_id = nodes_to_update.parent_id
                        FROM (VALUES {}) nodes_to_update(child_id, parent_id)
                        WHERE treenode.id = nodes_to_update.child_id;
                    """.format(update_nodes_template))
                    params = update_nodes_flattened

                delete_nodes_template = ",".join("(%s)" for _ in nodes_to_remove)
                query_parts.append("""
                    DELETE
                    FROM treenode
                    WHERE id IN (
                        SELECT t.id
                        FROM treenode t
                        JOIN (VALUES {}) to_delete(id)
                            ON t.id = to_delete.id
                    )
                    RETURNING id;
                """.format(delete_nodes_template))
                params = params + nodes_to_remove

                cursor.execute("\n".join(query_parts), params)
                deleted_node_ids = [r[0] for r in cursor.fetchall()]
                n_deleted_nodes = len(deleted_node_ids)

    sampler.delete()

    return JsonResponse({
        'deleted_sampler_id': sampler_id,
        'deleted_interval_nodes': n_deleted_nodes
    })
示例#14
0
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]))

    # 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)
    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):
            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
    treenode_id, skeleton_id = _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
    child.parent_id = treenode_id
    child.save()

    return HttpResponse(json.dumps({
        'treenode_id': treenode_id,
        'skeleton_id': skeleton_id
    }))
示例#15
0
    # 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)
    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):
            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)
示例#16
0
    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)
    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):
            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