Ejemplo n.º 1
0
def delete_treenode(request, project_id=None):
    """ Deletes a treenode. If the skeleton has a single node, deletes the
    skeleton and its neuron. Returns the parent_id, if any."""
    treenode_id = int(request.POST.get('treenode_id', -1))
    # Raise an Exception if the user doesn't have permission to edit the neuron
    # the skeleton of the treenode is modeling.
    can_edit_treenode_or_fail(request.user, project_id, treenode_id)
    #
    treenode = Treenode.objects.get(pk=treenode_id)
    parent_id = treenode.parent_id

    response_on_error = ''
    try:
        cursor = connection.cursor()
        if not parent_id:
            # This treenode is root.
            response_on_error = 'Could not retrieve children for treenode #%s' % treenode_id
            n_children = Treenode.objects.filter(parent=treenode).count()
            response_on_error = "Can't delete root node when it has children"
            if n_children > 0:
                # TODO yes you can, the new root is the first of the children, and other children become independent skeletons
                raise Exception("You can't delete the root node when it has children.")
            # Get the neuron before the skeleton is deleted. It can't be
            # accessed otherwise anymore.
            neuron = ClassInstance.objects.get(project_id=project_id,
                        cici_via_b__relation__relation_name='model_of',
                        cici_via_b__class_instance_a=treenode.skeleton)
            # Remove the original skeleton. It is OK to remove it if it only had
            # one node, even if the skeleton's user does not match or the user
            # is not superuser. Delete the skeleton, which triggers deleting
            # the ClassInstanceClassInstance relationship with neuron_id
            response_on_error = 'Could not delete skeleton.'
            # Extra check for errors, like having two root nodes
            count = Treenode.objects.filter(skeleton_id=treenode.skeleton_id).count()
            if 1 == count:
                ClassInstance.objects.filter(pk=treenode.skeleton_id).delete() # deletes as well treenodes that refer to the skeleton
            else:
                return HttpResponse(json.dumps({"error": "Can't delete isolated node: erroneously, its skeleton contains more than one treenode! Check for multiple root nodes."}))
            
            # If the neuron modeled by the skeleton of the treenode is empty,
            # delete it.
            response_on_error = 'Could not delete neuron #%s' % neuron.id
            _delete_if_empty(neuron.id)

        else:
            # Treenode is not root, it has a parent and perhaps children.
            # Reconnect all the children to the parent.
            response_on_error = 'Could not update parent id of children nodes'
            Treenode.objects.filter(parent=treenode).update(parent=treenode.parent)

        # Remove treenode
        response_on_error = 'Could not delete treenode.'
        Treenode.objects.filter(pk=treenode_id).delete()
        return HttpResponse(json.dumps({'parent_id': parent_id}))

    except Exception as e:
        raise Exception(response_on_error + ': ' + str(e))
Ejemplo n.º 2
0
def delete_treenode(request, project_id=None):
    """ If the skeleton has a single node, deletes the skeleton, and if so, if the skeleton is a model_of a neuron that was part_of group 'Isolated synaptic terminals', deletes the neuron. Returns the parent_id, if any."""
    treenode_id = int(request.POST.get('treenode_id', -1))
    # Raise an Exception if the user doesn't own the treenode or is not superuser
    can_edit_or_fail(request.user, treenode_id, 'treenode')
    #
    treenode = Treenode.objects.get(pk=treenode_id)
    parent_id = treenode.parent_id

    response_on_error = ''
    try:
        cursor = connection.cursor()
        if not parent_id:
            # This treenode is root.
            response_on_error = 'Could not retrieve children for treenode #%s' % treenode_id
            n_children = Treenode.objects.filter(parent=treenode).count()
            response_on_error = "Can't delete root node when it has children"
            if n_children > 0:
                # TODO yes you can, the new root is the first of the children, and other children become independent skeletons
                raise Exception("You can't delete the root node when it has children.")
            # Remove the original skeleton.
            # It is OK to remove it if it only had one node,
            # even if the skeleton's user does not match or the user is not superuser.
            # Fetch the neuron id, if it was a placeholder under 'Isolated synaptic terminals' group
            neuron_id = _in_isolated_synaptic_terminals(treenode.skeleton_id)
            # Delete the skeleton, which triggers deleting the ClassInstanceClassInstance relationship with neuron_id
            response_on_error = 'Could not delete skeleton.'
            # Extra check for errors, like having two root nodes
            count = Treenode.objects.filter(skeleton_id=treenode.skeleton_id).count()
            if 1 == count:
                ClassInstance.objects.filter(pk=treenode.skeleton_id).delete() # deletes as well treenodes that refer to the skeleton
            else:
                return HttpResponse(json.dumps({"error": "Can't delete isolated node: erroneously, its skeleton contains more than one treenode! Check for multiple root nodes."}))
            
            # If the neuron was part of the 'Isolated synaptic terminals' and no other skeleton is a model_of it, delete it
            if neuron_id:
                response_on_error = 'Could not delete neuron #%s' % neuron_id
                if _delete_if_empty(neuron_id):
                    print >> sys.stderr, "DELETED neuron %s from IST" % neuron_id

        else:
            # Treenode is not root, it has a parent and perhaps children.
            # Reconnect all the children to the parent.
            response_on_error = 'Could not update parent id of children nodes'
            Treenode.objects.filter(parent=treenode).update(parent=treenode.parent)

        # Remove treenode
        response_on_error = 'Could not delete treenode.'
        Treenode.objects.filter(pk=treenode_id).delete()
        return HttpResponse(json.dumps({'parent_id': parent_id}))

    except Exception as e:
        raise Exception(response_on_error + ': ' + str(e))
Ejemplo n.º 3
0
def delete_treenode(request, project_id=None):
    """ Deletes a treenode. If the skeleton has a single node, deletes the
    skeleton and its neuron. Returns the parent_id, if any."""
    treenode_id = int(request.POST.get('treenode_id', -1))
    # Raise an exception if the user doesn't have permission to edit the
    # treenode.
    can_edit_or_fail(request.user, treenode_id, 'treenode')
    # Raise an Exception if the user doesn't have permission to edit the neuron
    # the skeleton of the treenode is modeling.
    can_edit_treenode_or_fail(request.user, project_id, treenode_id)
    # Make sure the back-end is in the expected state
    state.validate_state(treenode_id,
                         request.POST.get('state'),
                         lock=True,
                         neighborhood=True)

    treenode = Treenode.objects.get(pk=treenode_id)
    parent_id = treenode.parent_id

    # Get information about linked connectors
    links = list(
        TreenodeConnector.objects.filter(project_id=project_id,
                                         treenode_id=treenode_id).values_list(
                                             'id', 'relation_id',
                                             'connector_id', 'confidence'))

    n_sampler_refs = SamplerInterval.objects.filter(start_node=treenode).count() + \
            SamplerInterval.objects.filter(end_node=treenode).count()
    if (n_sampler_refs > 0):
        raise ValueError(
            "Can't delete node, it is used in at least one sampler interval")

    response_on_error = ''
    deleted_neuron = False
    try:
        if not parent_id:
            children = []
            # This treenode is root.
            response_on_error = 'Could not retrieve children for ' \
                'treenode #%s' % treenode_id
            n_children = Treenode.objects.filter(parent=treenode).count()
            response_on_error = "Could not delete root node"
            if n_children > 0:
                # TODO yes you can, the new root is the first of the children,
                # and other children become independent skeletons
                raise Exception("You can't delete the root node when it "
                                "has children.")
            # Get the neuron before the skeleton is deleted. It can't be
            # accessed otherwise anymore.
            neuron = ClassInstance.objects.get(
                project_id=project_id,
                cici_via_b__relation__relation_name='model_of',
                cici_via_b__class_instance_a=treenode.skeleton)
            # Remove the original skeleton. It is OK to remove it if it only had
            # one node, even if the skeleton's user does not match or the user
            # is not superuser. Delete the skeleton, which triggers deleting
            # the ClassInstanceClassInstance relationship with neuron_id
            response_on_error = 'Could not delete skeleton.'
            # Extra check for errors, like having two root nodes
            count = Treenode.objects.filter(skeleton_id=treenode.skeleton_id) \
                .count()
            if 1 == count:
                # deletes as well treenodes that refer to the skeleton
                ClassInstance.objects.filter(pk=treenode.skeleton_id) \
                    .delete()
            else:
                return JsonResponse({"error": "Can't delete " \
                    "isolated node: erroneously, its skeleton contains more " \
                    "than one treenode! Check for multiple root nodes."})

            # If the neuron modeled by the skeleton of the treenode is empty,
            # delete it.
            response_on_error = 'Could not delete neuron #%s' % neuron.id
            deleted_neuron = _delete_if_empty(neuron.id)

            if deleted_neuron:
                # Insert log entry for neuron deletion
                insert_into_log(
                    project_id, request.user.id, 'remove_neuron',
                    (treenode.location_x, treenode.location_y,
                     treenode.location_z),
                    'Deleted neuron %s and skeleton(s) %s.' %
                    (neuron.id, treenode.skeleton_id))

        else:
            # Treenode is not root, it has a parent and perhaps children.
            # Reconnect all the children to the parent.
            response_on_error = 'Could not update parent id of children nodes'
            cursor = connection.cursor()
            cursor.execute(
                """
                UPDATE treenode SET parent_id = %s
                WHERE project_id = %s AND parent_id = %s
                RETURNING id, edition_time
            """, (treenode.parent_id, project_id, treenode.id))
            # Children will be a list of two-element lists, just what we want to
            # return as child info.
            children = cursor.fetchall()

        # Remove treenode
        response_on_error = 'Could not delete treenode.'
        Treenode.objects.filter(project_id=project_id, pk=treenode_id).delete()
        return JsonResponse({
            'x': treenode.location_x,
            'y': treenode.location_y,
            'z': treenode.location_z,
            'parent_id': parent_id,
            'children': children,
            'links': links,
            'radius': treenode.radius,
            'confidence': treenode.confidence,
            'skeleton_id': treenode.skeleton_id,
            'deleted_neuron': deleted_neuron,
            'success': "Removed treenode successfully."
        })

    except Exception as e:
        raise Exception(response_on_error + ': ' + str(e))
Ejemplo n.º 4
0
def _join_skeleton(user, from_treenode_id, to_treenode_id, project_id):
    """ Take the IDs of two nodes, each belonging to a different skeleton,
    and make to_treenode be a child of from_treenode,
    and join the nodes of the skeleton of to_treenode
    into the skeleton of from_treenode,
    and delete the former skeleton of to_treenode."""
    if from_treenode_id is None or to_treenode_id is None:
        raise Exception('Missing arguments to _join_skeleton')

    response_on_error = ''
    try:
        to_treenode_id = int(to_treenode_id)
        cursor = connection.cursor()
        cursor.execute('''
        SELECT class_instance.user_id,
               treenode.skeleton_id,
               treenode.user_id
        FROM class_instance,
             treenode
        WHERE treenode.id = %s
          AND treenode.skeleton_id = class_instance.id
        ''' % to_treenode_id)
        to_skeleton_user_id, to_skid, to_treenode_user_id = cursor.fetchone()

        # Check if joining is allowed
        if 0 == Treenode.objects.filter(parent_id=to_treenode_id).count() and Treenode.objects.filter(pk=to_treenode_id).values_list('parent_id')[0][0] is None:
            # Is an isolated node, so it can be joined freely
            pass
        # If the treenode is not isolated, must own the skeleton or be superuser
        elif user.is_superuser or user.id == to_skeleton_user_id:
            pass
        # If the skeleton is a model_of a neuron that is part_of the 'Fragments' group
        # or the 'Isolated synaptic terminals' group, then it can be joined
        elif _under_fragments(to_skid):
            pass
        # Else, if the user owns the node (but not the skeleton), the join is possible only if all other nodes also belong to the user (such a situation occurs when the user ows both skeletons to join, or when part of a skeleton is split away from a larger one that belongs to someone else)
        elif user.id == to_treenode_user_id and 0 == Treenode.objects.filter(skeleton_id=to_skid).exclude(user=user).count():
            pass
        else:
            raise Exception("User %s with id #%s cannot join skeleton #%s, because the user doesn't own the skeleton or the skeleton contains nodes that belong to someone else." % (user.username, user.id, to_skid))

        from_treenode_id = int(from_treenode_id)
        from_treenode = Treenode.objects.get(pk=from_treenode_id)
        from_skid = from_treenode.skeleton_id

        if from_skid == to_skid:
            raise Exception('Cannot join treenodes of the same skeleton, this would introduce a loop.')
        
        from_neuron = _get_neuronname_from_skeletonid( project_id, from_skid )
        to_neuron = _get_neuronname_from_skeletonid( project_id, to_skid )

        # Reroot to_skid at to_treenode if necessary
        response_on_error = 'Could not reroot at treenode %s' % to_treenode_id
        _reroot_skeleton(to_treenode_id, project_id)

        # The target skeleton is removed and its treenode assumes
        # the skeleton id of the from-skeleton.

        response_on_error = 'Could not update Treenode table with new skeleton id for joined treenodes.'
        Treenode.objects.filter(skeleton=to_skid).update(skeleton=from_skid)

        response_on_error = 'Could not update TreenodeConnector table.'
        TreenodeConnector.objects.filter(
            skeleton=to_skid).update(skeleton=from_skid)

        # Determine if the neuron is part_of group 'Isolated synaptic terminals'
        response_on_error = 'Could not find neuron of skeleton #%s.' % to_skid
        neuron_id = _in_isolated_synaptic_terminals(to_skid)

        # Remove skeleton of to_id (deletes cicic part_of to neuron by cascade,
        # leaving the parent neuron dangling in the object tree).
        response_on_error = 'Could not delete skeleton with ID %s.' % to_skid
        ClassInstance.objects.filter(pk=to_skid).delete()

        # Remove the neuron if it belongs to 'Isolated synaptic terminals'
        # It is ok if the request.user doesn't match with the neuron's user_id or is not superuser.
        if neuron_id:
            response_on_error = 'Could not delete neuron with id %s.' % neuron_id
            if _delete_if_empty(neuron_id):
                print >> sys.stderr, "DELETED neuron %s from IST" % neuron_id

        # Update the parent of to_treenode.
        response_on_error = 'Could not update parent of treenode with ID %s' % to_treenode_id
        Treenode.objects.filter(id=to_treenode_id).update(parent=from_treenode_id, editor=user)

        insert_into_log(project_id, user.id, 'join_skeleton', from_treenode.location, 'Joined skeleton with ID %s (neuron: %s) into skeleton with ID %s (neuron: %s)' % (to_skid, to_neuron['neuronname'], from_skid, from_neuron['neuronname']) )

    except Exception as e:
        raise Exception(response_on_error + ':' + str(e))
Ejemplo n.º 5
0
def delete_treenode(request, project_id=None):
    """ Deletes a treenode. If the skeleton has a single node, deletes the
    skeleton and its neuron. Returns the parent_id, if any."""
    treenode_id = int(request.POST.get('treenode_id', -1))
    # Raise an exception if the user doesn't have permission to edit the
    # treenode.
    can_edit_or_fail(request.user, treenode_id, 'treenode')
    # Raise an Exception if the user doesn't have permission to edit the neuron
    # the skeleton of the treenode is modeling.
    can_edit_treenode_or_fail(request.user, project_id, treenode_id)
    # Make sure the back-end is in the expected state
    state.validate_state(treenode_id, request.POST.get('state'), lock=True,
            neighborhood=True)

    treenode = Treenode.objects.get(pk=treenode_id)
    parent_id = treenode.parent_id

    # Get information about linked connectors
    links = list(TreenodeConnector.objects.filter(project_id=project_id,
            treenode_id=treenode_id).values_list('id', 'relation_id',
            'connector_id', 'confidence'))

    n_sampler_refs = SamplerInterval.objects.filter(start_node=treenode).count() + \
            SamplerInterval.objects.filter(end_node=treenode).count()
    if (n_sampler_refs > 0):
        raise ValueError("Can't delete node, it is used in at least one sampler interval")

    response_on_error = ''
    deleted_neuron = False
    cursor = connection.cursor()
    try:
        if not parent_id:
            children = []
            # This treenode is root.
            response_on_error = 'Could not retrieve children for ' \
                'treenode #%s' % treenode_id
            n_children = Treenode.objects.filter(parent=treenode).count()
            response_on_error = "Could not delete root node"
            if n_children > 0:
                # TODO yes you can, the new root is the first of the children,
                # and other children become independent skeletons
                raise Exception("You can't delete the root node when it "
                                "has children.")
            # Get the neuron before the skeleton is deleted. It can't be
            # accessed otherwise anymore.
            neuron = ClassInstance.objects.get(project_id=project_id,
                        cici_via_b__relation__relation_name='model_of',
                        cici_via_b__class_instance_a=treenode.skeleton)
            # Remove the original skeleton. It is OK to remove it if it only had
            # one node, even if the skeleton's user does not match or the user
            # is not superuser. Delete the skeleton, which triggers deleting
            # the ClassInstanceClassInstance relationship with neuron_id
            response_on_error = 'Could not delete skeleton.'
            # Extra check for errors, like having two root nodes
            count = Treenode.objects.filter(skeleton_id=treenode.skeleton_id) \
                .count()
            if 1 == count:
                # deletes as well treenodes that refer to the skeleton
                ClassInstance.objects.filter(pk=treenode.skeleton_id) \
                    .delete()
            else:
                return JsonResponse({"error": "Can't delete " \
                    "isolated node: erroneously, its skeleton contains more " \
                    "than one treenode! Check for multiple root nodes."})

            # If the neuron modeled by the skeleton of the treenode is empty,
            # delete it.
            response_on_error = 'Could not delete neuron #%s' % neuron.id
            deleted_neuron = _delete_if_empty(neuron.id)

            if deleted_neuron:
                # Insert log entry for neuron deletion
                insert_into_log(project_id, request.user.id, 'remove_neuron',
                               (treenode.location_x, treenode.location_y, treenode.location_z),
                               'Deleted neuron %s and skeleton(s) %s.' % (neuron.id, treenode.skeleton_id))

        else:
            # Treenode is not root, it has a parent and perhaps children.
            # Reconnect all the children to the parent.
            response_on_error = 'Could not update parent id of children nodes'
            cursor.execute("""
                UPDATE treenode SET parent_id = %s
                WHERE project_id = %s AND parent_id = %s
                RETURNING id, edition_time
            """, (treenode.parent_id, project_id, treenode.id))
            # Children will be a list of two-element lists, just what we want to
            # return as child info.
            children = cursor.fetchall()

        # Remove treenode. Set the current user name in a transaction local
        # variable. This is done to communicate the current user to the trigger
        # that updates the skeleton summary table.
        response_on_error = 'Could not delete treenode.'
        cursor.execute("SET LOCAL catmaid.user_id=%(user_id)s", {
            'user_id': request.user.id,
        })
        Treenode.objects.filter(project_id=project_id, pk=treenode_id).delete()
        return JsonResponse({
            'x': treenode.location_x,
            'y': treenode.location_y,
            'z': treenode.location_z,
            'parent_id': parent_id,
            'children': children,
            'links': links,
            'radius': treenode.radius,
            'confidence': treenode.confidence,
            'skeleton_id': treenode.skeleton_id,
            'deleted_neuron': deleted_neuron,
            'success': "Removed treenode successfully."
        })

    except Exception as e:
        raise Exception(response_on_error + ': ' + str(e))
Ejemplo n.º 6
0
def _join_skeleton(user, from_treenode_id, to_treenode_id, project_id,
        annotation_set):
    """ Take the IDs of two nodes, each belonging to a different skeleton, and
    make to_treenode be a child of from_treenode, and join the nodes of the
    skeleton of to_treenode into the skeleton of from_treenode, and delete the
    former skeleton of to_treenode. All annotations in annotation_set will be
    linked to the skeleton of to_treenode."""
    if from_treenode_id is None or to_treenode_id is None:
        raise Exception('Missing arguments to _join_skeleton')

    response_on_error = ''
    try:
        from_treenode_id = int(from_treenode_id)
        to_treenode_id = int(to_treenode_id)

        try:
            from_treenode = Treenode.objects.get(pk=from_treenode_id)
        except Treenode.DoesNotExist:
            raise Exception("Could not find a skeleton for treenode #%s" % from_treenode_id)

        try:
            to_treenode = Treenode.objects.get(pk=to_treenode_id)
        except Treenode.DoesNotExist:
            raise Exception("Could not find a skeleton for treenode #%s" % to_treenode_id)

        from_skid = from_treenode.skeleton_id
        from_neuron = _get_neuronname_from_skeletonid( project_id, from_skid )

        to_skid = to_treenode.skeleton_id
        to_neuron = _get_neuronname_from_skeletonid( project_id, to_skid )

        # Make sure the user has permissions to edit both neurons
        can_edit_class_instance_or_fail(
                user, from_neuron['neuronid'], 'neuron')
        can_edit_class_instance_or_fail(
                user, to_neuron['neuronid'], 'neuron')

        # Check if annotations are valid
        if not check_annotations_on_join(project_id, user,
                from_neuron['neuronid'], to_neuron['neuronid'], annotation_set):
            raise Exception("Annotation distribution is not valid for joining. " \
              "Annotations for which you don't have permissions have to be kept!")

        if from_skid == to_skid:
            raise Exception('Cannot join treenodes of the same skeleton, this would introduce a loop.')

        # Reroot to_skid at to_treenode if necessary
        response_on_error = 'Could not reroot at treenode %s' % to_treenode_id
        _reroot_skeleton(to_treenode_id, project_id)

        # The target skeleton is removed and its treenode assumes
        # the skeleton id of the from-skeleton.

        response_on_error = 'Could not update Treenode table with new skeleton id for joined treenodes.'
        Treenode.objects.filter(skeleton=to_skid).update(skeleton=from_skid)

        response_on_error = 'Could not update TreenodeConnector table.'
        TreenodeConnector.objects.filter(
            skeleton=to_skid).update(skeleton=from_skid)

        # Remove skeleton of to_id (deletes cicic part_of to neuron by cascade,
        # leaving the parent neuron dangling in the object tree).
        response_on_error = 'Could not delete skeleton with ID %s.' % to_skid
        ClassInstance.objects.filter(pk=to_skid).delete()

        # Remove the 'losing' neuron if it is empty
        _delete_if_empty(to_neuron['neuronid'])

        # Update the parent of to_treenode.
        response_on_error = 'Could not update parent of treenode with ID %s' % to_treenode_id
        Treenode.objects.filter(id=to_treenode_id).update(parent=from_treenode_id, editor=user)

        # Update linked annotations of neuron
        response_on_error = 'Could not update annotations of neuron ' \
                'with ID %s' % from_neuron['neuronid']
        _update_neuron_annotations(project_id, user, from_neuron['neuronid'],
                annotation_set)

        insert_into_log(project_id, user.id, 'join_skeleton',
                from_treenode.location, 'Joined skeleton with ID %s (neuron: ' \
                '%s) into skeleton with ID %s (neuron: %s, annotations: %s)' % \
                (to_skid, to_neuron['neuronname'], from_skid,
                        from_neuron['neuronname'], ', '.join(annotation_set)))

    except Exception as e:
        raise Exception(response_on_error + ':' + str(e))
Ejemplo n.º 7
0
def delete_treenode(request, project_id=None):
    """ Deletes a treenode. If the skeleton has a single node, deletes the
    skeleton and its neuron. Returns the parent_id, if any."""
    treenode_id = int(request.POST.get('treenode_id', -1))
    # Raise an exception if the user doesn't have permission to edit the
    # treenode.
    can_edit_or_fail(request.user, treenode_id, 'treenode')
    # Raise an Exception if the user doesn't have permission to edit the neuron
    # the skeleton of the treenode is modeling.
    can_edit_treenode_or_fail(request.user, project_id, treenode_id)

    treenode = Treenode.objects.get(pk=treenode_id)
    parent_id = treenode.parent_id

    response_on_error = ''
    deleted_neuron = False
    try:
        if not parent_id:
            # This treenode is root.
            response_on_error = 'Could not retrieve children for ' \
                'treenode #%s' % treenode_id
            n_children = Treenode.objects.filter(parent=treenode).count()
            response_on_error = "Could not delete root node"
            if n_children > 0:
                # TODO yes you can, the new root is the first of the children,
                # and other children become independent skeletons
                raise Exception("You can't delete the root node when it "
                                "has children.")
            # Get the neuron before the skeleton is deleted. It can't be
            # accessed otherwise anymore.
            neuron = ClassInstance.objects.get(
                project_id=project_id,
                cici_via_b__relation__relation_name='model_of',
                cici_via_b__class_instance_a=treenode.skeleton)
            # Remove the original skeleton. It is OK to remove it if it only had
            # one node, even if the skeleton's user does not match or the user
            # is not superuser. Delete the skeleton, which triggers deleting
            # the ClassInstanceClassInstance relationship with neuron_id
            response_on_error = 'Could not delete skeleton.'
            # Extra check for errors, like having two root nodes
            count = Treenode.objects.filter(skeleton_id=treenode.skeleton_id) \
                .count()
            if 1 == count:
                # deletes as well treenodes that refer to the skeleton
                ClassInstance.objects.filter(pk=treenode.skeleton_id) \
                    .delete()
            else:
                return HttpResponse(json.dumps({"error": "Can't delete " \
                    "isolated node: erroneously, its skeleton contains more " \
                    "than one treenode! Check for multiple root nodes."}))

            # If the neuron modeled by the skeleton of the treenode is empty,
            # delete it.
            response_on_error = 'Could not delete neuron #%s' % neuron.id
            deleted_neuron = _delete_if_empty(neuron.id)

        else:
            # Treenode is not root, it has a parent and perhaps children.
            # Reconnect all the children to the parent.
            response_on_error = 'Could not update parent id of children nodes'
            Treenode.objects.filter(parent=treenode) \
                .update(parent=treenode.parent)

        # Remove treenode
        response_on_error = 'Could not delete treenode.'
        Treenode.objects.filter(pk=treenode_id).delete()
        return HttpResponse(
            json.dumps({
                'deleted_neuron': deleted_neuron,
                'parent_id': parent_id,
                'skeleton_id': treenode.skeleton_id,
                'success': "Removed treenode successfully."
            }))

    except Exception as e:
        raise Exception(response_on_error + ': ' + str(e))