parameters: (user, project_id, arborescence, neuron_id=None,
          skeleton_id=None, name=None, annotations=['Import'], force=False,
          auto_id=True, source_id=None, source_url=None, source_project_id=None,
          source_type='skeleton', extended_data=False, map_available_users=True,
          replace_annotations=False)
return_statement: return {
          'neuron_id': neuron_id,
          'skeleton_id': new_skeleton.id,
          'graph': arborescence,
          'has_new_neuron_id': has_new_neuron_id,
          'has_new_skeleton_id': has_new_skeleton_id,
      }
docstring: Create a skeleton from a networkx directed tree.
  
      Associate the skeleton to the specified neuron, or a new one if none is
      provided. Returns a dictionary of the neuron and skeleton IDs, and the
      original arborescence with attributes added for treenode IDs.
docstring_summary: Create a skeleton from a networkx directed tree.
docstring_tokens: Create a skeleton from a networkx directed tree .
function: def _import_skeleton(user, project_id, arborescence, neuron_id=None,
          skeleton_id=None, name=None, annotations=['Import'], force=False,
          auto_id=True, source_id=None, source_url=None, source_project_id=None,
          source_type='skeleton', extended_data=False, map_available_users=True,
          replace_annotations=False) -> Dict[str, Any]:
      """Create a skeleton from a networkx directed tree.
  
      Associate the skeleton to the specified neuron, or a new one if none is
      provided. Returns a dictionary of the neuron and skeleton IDs, and the
      original arborescence with attributes added for treenode IDs.
      """
      # TODO: There is significant reuse here of code from create_treenode that
      # could be DRYed up.
      relation_map = get_relation_to_id_map(project_id)
      class_map = get_class_to_id_map(project_id)
  
      create_neuron_skeleton_link = False
  
      new_neuron = None
      new_skeleton = None
  
      if neuron_id is not None:
          # Check that the neuron to use exists
          try:
              existing_neuron = ClassInstance.objects.select_related('class_column').get(pk=neuron_id)
              if force:
                  if existing_neuron.project_id != project_id:
                      raise ValueError(f"Target neuron exists, but is part of other project (neuron ID: {neuron_id}, project ID: {existing_neuron.project_id}, new project ID: {project_id}")
  
                  if existing_neuron.class_column.class_name != 'neuron':
                      raise ValueError(f"Existing object with ID {existing_neuron.id} is not a neuron, " + \
                                       f"but is marked as {existing_neuron.class_column.class_name}")
  
                  # Remove all skeleton data linked to this neuron
                  cici = ClassInstanceClassInstance.objects.filter(
                          class_instance_b=neuron_id,
                          relation_id=relation_map['model_of'],
                          class_instance_a__class_column_id=class_map['skeleton'])
  
                  # Raise an Exception if the user doesn't have permission to
                  # edit the existing neuron.
                  can_edit_class_instance_or_fail(user, neuron_id, 'neuron')
                  # Raise an Exception if the user doesn't have permission to
                  # edit the existing skeleton.
                  for skeleton_link in cici:
                      old_skeleton = skeleton_link.class_instance_a
                      # Require users to have edit permission on the skeleton and
                      # all its treenodes.
                      can_edit_class_instance_or_fail(user, old_skeleton.id, 'class_instance')
                      treenodes = Treenode.objects.filter(skeleton_id=old_skeleton.id,
                              project_id=project_id)
                      treenode_ids = treenodes.values_list('id', flat=True)
                      can_edit_all_or_fail(user, treenode_ids, 'treenode')
  
                      # Remove existing skeletons unless it matches the current
                      # skeleton ID or wasn't provided. In that case the old
                      # skeleton is reused.
                      if skeleton_id in (None, old_skeleton.id):
                          new_skeleton = old_skeleton
                      else:
                          create_neuron_skeleton_link = True
                          skeleton_link.delete()
                          old_skeleton.delete()
  
                      treenodes.delete()
  
                  new_neuron = existing_neuron
              elif auto_id:
                  # The neuron ID exists already, and with force=False no data
                  # will be replaced.
                  neuron_id = None
              else:
                  raise ValueError("The passed in neuron ID is already in use and "
                          "neither of the parameters force or auto_id are set to true.")
          except ClassInstance.DoesNotExist:
              # The neuron ID is okay to use
              pass
  
      # Take care of a passed in skeleton if this didn't happen already
      if skeleton_id is not None and new_skeleton is None:
          # Check that the skeleton to use exists
          try:
              existing_skeleton = ClassInstance.objects.get(pk=skeleton_id)
              if force:
                  if existing_skeleton.project_id != project_id:
                      raise ValueError("Target skeleton exists, but is part of other project")
  
                  if existing_skeleton.class_column.class_name != 'skeleton':
                      raise ValueError(f"Existing object with ID {existing_skeleton.id} is not a skeleton, " + \
                                       f"but marked as {existing_skeleton.class_column.class_name}")
  
                  # Remove all data linked to this neuron, including skeletons
                  cici = ClassInstanceClassInstance.objects.filter(
                          class_instance_a=skeleton_id,
                          relation_id=relation_map['model_of'],
                          class_instance_b__class_column_id=class_map['neuron'])
                  if len(cici) > 1:
                      raise ValueError(f"Found more than one neuron link for skeleton {skeleton_id}")
                  existing_neuron_id = cici[0].class_instance_b
  
                  # Raise an Exception if the user doesn't have permission to
                  # edit the existing skeleton.
                  can_edit_class_instance_or_fail(user, skeleton_id, 'skeleton')
                  # Require users to have edit permission on all treenodes of the
                  # skeleton.
                  treenodes = Treenode.objects.filter(skeleton_id=skeleton_id,
                          project_id=project_id)
                  treenode_ids = treenodes.values_list('id', flat=True)
                  if treenode_ids:
                      # Raise an Exception if the user doesn't have permission to
                      # edit the existing treenodes.
                      can_edit_all_or_fail(user, treenode_ids, 'treenode')
  
                  # Rremove all treenodes of existing skeletons. If a neuron ID is
                  # passed in and it is different from the existing neureon ID,
                  # the neuron is deleted as well.
                  for link in cici:
                      old_neuron = link.class_instance_b
                      can_edit_class_instance_or_fail(user, old_neuron.id, 'class_instance')
  
                      # Remove existing neuron, if it is different from a passed
                      # in neurom ID. If no neuron ID was passed in, we just continue
                      # using the existing one (along with everything attached to it).
                      if neuron_id in (None, existing_neuron_id):
                          new_neuron = old_neuron
                      else:
                          link.delete()
                          old_neuron.delete()
  
                      treenodes.delete()
  
                  new_skeleton = existing_skeleton
              elif auto_id:
                  # The skeleton ID exists already, and with force=False no data
                  # will be replaced.
                  skeleton_id = None
              else:
                  raise ValueError("The passed in skeleton ID is already in use and "
                          "neither of the parameters force or auto_id are set to true.")
          except ClassInstance.DoesNotExist:
              # The skeleton ID is okay to use
              pass
  
      if not new_skeleton:
          new_skeleton = ClassInstance()
          new_skeleton.id = skeleton_id
  
      new_skeleton.user = user
      new_skeleton.project_id = project_id
      new_skeleton.class_column_id = class_map['skeleton']
      if name is not None:
          new_skeleton.name = name
      else:
          new_skeleton.name = 'skeleton'
          new_skeleton.save()
          new_skeleton.name = 'skeleton %d' % new_skeleton.id
  
      has_new_skeleton_id = new_skeleton.id is None
  
      new_skeleton.save()
      skeleton_id = new_skeleton.id
  
      def relate_neuron_to_skeleton(neuron, skeleton):
          return _create_relation(user, project_id,
                  relation_map['model_of'], skeleton, neuron)
  
      if not new_neuron:
          new_neuron = ClassInstance()
          new_neuron.id = neuron_id
          create_neuron_skeleton_link = True
  
      new_neuron.user = user
      new_neuron.project_id = project_id
      new_neuron.class_column_id = class_map['neuron']
      if name is not None:
          new_neuron.name = name
      elif neuron_id is None: # Don't override existing neuron names
          new_neuron.name = 'neuron'
          new_neuron.save()
          new_neuron.name = 'neuron %d' % new_neuron.id
  
      has_new_neuron_id = new_neuron.id is None
  
      new_neuron.save()
      neuron_id = new_neuron.id
  
      if create_neuron_skeleton_link:
          relate_neuron_to_skeleton(neuron_id, new_skeleton.id)
  
      # Add annotations, if that is requested. This will only by default append to
      # any existing annotations for this neuron (none for new neurons). If
      # replace_annotations is True, all existing annotations will be replaced.
      if replace_annotations:
          clear_annotations(project_id, new_skeleton.id)
  
      if annotations:
          annotation_map = {a:{'user_id': user.id} for a in annotations}
          _annotate_entities(project_id, [new_neuron.id], annotation_map)
  
      # For pathological networks this can error, so do it before inserting
      # treenodes.
      root = find_root(arborescence)
      if root is None:
          raise ValueError('No root, provided graph is malformed!')
  
      # Bulk create the required number of treenodes. This must be done in two
      # steps because treenode IDs are not known.
      cursor = connection.cursor()
      cursor.execute("""
          INSERT INTO treenode (project_id, location_x, location_y, location_z,
              editor_id, user_id, skeleton_id)
          SELECT t.project_id, t.x, t.x, t.x, t.user_id, t.user_id, t.skeleton_id
          FROM (VALUES (%(project_id)s, 0, %(user_id)s, %(skeleton_id)s))
              AS t (project_id, x, user_id, skeleton_id),
              generate_series(1, %(num_treenodes)s)
          RETURNING treenode.id
      """, {
          'project_id': int(project_id),
          'user_id': user.id,
          'skeleton_id': new_skeleton.id,
          'num_treenodes': arborescence.number_of_nodes()
      })
      treenode_ids = cursor.fetchall()
      # Flatten IDs
      treenode_ids = list(chain.from_iterable(treenode_ids))
      nx.set_node_attributes(arborescence, name='id', values=dict(zip(arborescence.nodes(), treenode_ids)))
  
      # Set parent node ID
      for n, nbrs in arborescence.adjacency():
          for nbr in nbrs:
              # FIXME: the cast here and below in the SQL (::bigint) shouldn't be
              # needed
              arborescence.nodes[nbr]['parent_id'] = int(arborescence.nodes[n]['id'])
              if 'radius' not in arborescence.nodes[nbr]:
                  arborescence.nodes[nbr]['radius'] = -1
      arborescence.nodes[root]['parent_id'] = None
      if 'radius' not in arborescence.nodes[root]:
          arborescence.nodes[root]['radius'] = -1
      new_location = tuple([arborescence.nodes[root][k] for k in ('x', 'y', 'z')])
  
      if extended_data:
          treenode_template = '(' + '),('.join(
              '%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s' for _ in arborescence.nodes
          ) + ')'
          treenode_values = list(chain.from_iterable(
              [
                  d['id'], d['x'], d['y'], d['z'],
                  d['parent_id'], d['radius'], d['user_id'],
                  d['creation_time'], d['editor_id'],
                  d['edition_time'], d['confidence']
              ] for n, d in arborescence.nodes(data=True)
          ))
          # Include skeleton ID for index performance.
          cursor.execute(f"""
              UPDATE treenode SET
                  location_x = v.x,
                  location_y = v.y,
                  location_z = v.z,
                  parent_id = v.parent_id::bigint,
                  radius = v.radius,
                  user_id = v.user_id,
                  creation_time = v.creation_time,
                  editor_id = v.editor_id,
                  edition_time = v.edition_time,
                  confidence = v.confidence
              FROM (VALUES {treenode_template}) AS v(id, x, y, z, parent_id,
                  radius, user_id, creation_time, editor_id, edition_time,
                  confidence)
              WHERE treenode.id = v.id
                  AND treenode.skeleton_id = %s
          """, treenode_values + [new_skeleton.id])
      else:
          treenode_template = '(' + '),('.join('%s,%s,%s,%s,%s,%s' for _ in arborescence.nodes) + ')'
          treenode_values = list(chain.from_iterable([d['id'], d['x'], d['y'], d['z'], d['parent_id'], d['radius']] \
                  for n, d in arborescence.nodes(data=True)))
          # Include skeleton ID for index performance.
          cursor.execute(f"""
              UPDATE treenode SET
                  location_x = v.x,
                  location_y = v.y,
                  location_z = v.z,
                  parent_id = v.parent_id,
                  radius = v.radius
              FROM (VALUES {treenode_template}) AS v(id, x, y, z, parent_id, radius)
              WHERE treenode.id = v.id
                  AND treenode.skeleton_id = %s
          """, treenode_values + [new_skeleton.id])
  
      # Log import.
      annotation_info = f' {", ".join(annotations)}' if annotations else ''
      insert_into_log(project_id, user.id, 'create_neuron',
                      new_location, f'Create neuron {new_neuron.id} and skeleton '
                      f'{new_skeleton.id} via import.{annotation_info}')
  
      # Store reference to source ID and source URL, if provided.
      if source_url and source_project_id:
          data_source = get_data_source(project_id, source_url, source_project_id, user.id)
          skeleton_origin = SkeletonOrigin.objects.create(project_id=project_id,
                  user_id=user.id, data_source=data_source,
                  skeleton_id=new_skeleton.id, source_id=source_id,
                  source_type=source_type)
  
      if neuron_id or skeleton_id:
          # Reset ID sequence if IDs have been passed in.
          cursor.execute("""
              SELECT setval('concept_id_seq', coalesce(max("id"), 1), max("id") IS NOT null)
              FROM concept;
              SELECT setval('location_id_seq', coalesce(max("id"), 1), max("id") IS NOT null)
              FROM location;
          """)
  
      return {
          'neuron_id': neuron_id,
          'skeleton_id': new_skeleton.id,
          'graph': arborescence,
          'has_new_neuron_id': has_new_neuron_id,
          'has_new_skeleton_id': has_new_skeleton_id,
      }
function_tokens: def _import_skeleton ( user , project_id , arborescence , neuron_id = None , skeleton_id = None , name = None , annotations = [ 'Import' ] , force = False , auto_id = True , source_id = None , source_url = None , source_project_id = None , source_type = 'skeleton' , extended_data = False , map_available_users = True , replace_annotations = False ) -> Dict [ str , Any ] : # TODO: There is significant reuse here of code from create_treenode that # could be DRYed up. relation_map = get_relation_to_id_map ( project_id ) class_map = get_class_to_id_map ( project_id ) create_neuron_skeleton_link = False new_neuron = None new_skeleton = None if neuron_id is not None : # Check that the neuron to use exists try : existing_neuron = ClassInstance . objects . select_related ( 'class_column' ) . get ( pk = neuron_id ) if force : if existing_neuron . project_id != project_id : raise ValueError ( f"Target neuron exists, but is part of other project (neuron ID: {neuron_id}, project ID: {existing_neuron.project_id}, new project ID: {project_id}" ) if existing_neuron . class_column . class_name != 'neuron' : raise ValueError ( f"Existing object with ID {existing_neuron.id} is not a neuron, " + f"but is marked as {existing_neuron.class_column.class_name}" ) # Remove all skeleton data linked to this neuron cici = ClassInstanceClassInstance . objects . filter ( class_instance_b = neuron_id , relation_id = relation_map [ 'model_of' ] , class_instance_a__class_column_id = class_map [ 'skeleton' ] ) # Raise an Exception if the user doesn't have permission to # edit the existing neuron. can_edit_class_instance_or_fail ( user , neuron_id , 'neuron' ) # Raise an Exception if the user doesn't have permission to # edit the existing skeleton. for skeleton_link in cici : old_skeleton = skeleton_link . class_instance_a # Require users to have edit permission on the skeleton and # all its treenodes. can_edit_class_instance_or_fail ( user , old_skeleton . id , 'class_instance' ) treenodes = Treenode . objects . filter ( skeleton_id = old_skeleton . id , project_id = project_id ) treenode_ids = treenodes . values_list ( 'id' , flat = True ) can_edit_all_or_fail ( user , treenode_ids , 'treenode' ) # Remove existing skeletons unless it matches the current # skeleton ID or wasn't provided. In that case the old # skeleton is reused. if skeleton_id in ( None , old_skeleton . id ) : new_skeleton = old_skeleton else : create_neuron_skeleton_link = True skeleton_link . delete ( ) old_skeleton . delete ( ) treenodes . delete ( ) new_neuron = existing_neuron elif auto_id : # The neuron ID exists already, and with force=False no data # will be replaced. neuron_id = None else : raise ValueError ( "The passed in neuron ID is already in use and " "neither of the parameters force or auto_id are set to true." ) except ClassInstance . DoesNotExist : # The neuron ID is okay to use pass # Take care of a passed in skeleton if this didn't happen already if skeleton_id is not None and new_skeleton is None : # Check that the skeleton to use exists try : existing_skeleton = ClassInstance . objects . get ( pk = skeleton_id ) if force : if existing_skeleton . project_id != project_id : raise ValueError ( "Target skeleton exists, but is part of other project" ) if existing_skeleton . class_column . class_name != 'skeleton' : raise ValueError ( f"Existing object with ID {existing_skeleton.id} is not a skeleton, " + f"but marked as {existing_skeleton.class_column.class_name}" ) # Remove all data linked to this neuron, including skeletons cici = ClassInstanceClassInstance . objects . filter ( class_instance_a = skeleton_id , relation_id = relation_map [ 'model_of' ] , class_instance_b__class_column_id = class_map [ 'neuron' ] ) if len ( cici ) > 1 : raise ValueError ( f"Found more than one neuron link for skeleton {skeleton_id}" ) existing_neuron_id = cici [ 0 ] . class_instance_b # Raise an Exception if the user doesn't have permission to # edit the existing skeleton. can_edit_class_instance_or_fail ( user , skeleton_id , 'skeleton' ) # Require users to have edit permission on all treenodes of the # skeleton. treenodes = Treenode . objects . filter ( skeleton_id = skeleton_id , project_id = project_id ) treenode_ids = treenodes . values_list ( 'id' , flat = True ) if treenode_ids : # Raise an Exception if the user doesn't have permission to # edit the existing treenodes. can_edit_all_or_fail ( user , treenode_ids , 'treenode' ) # Rremove all treenodes of existing skeletons. If a neuron ID is # passed in and it is different from the existing neureon ID, # the neuron is deleted as well. for link in cici : old_neuron = link . class_instance_b can_edit_class_instance_or_fail ( user , old_neuron . id , 'class_instance' ) # Remove existing neuron, if it is different from a passed # in neurom ID. If no neuron ID was passed in, we just continue # using the existing one (along with everything attached to it). if neuron_id in ( None , existing_neuron_id ) : new_neuron = old_neuron else : link . delete ( ) old_neuron . delete ( ) treenodes . delete ( ) new_skeleton = existing_skeleton elif auto_id : # The skeleton ID exists already, and with force=False no data # will be replaced. skeleton_id = None else : raise ValueError ( "The passed in skeleton ID is already in use and " "neither of the parameters force or auto_id are set to true." ) except ClassInstance . DoesNotExist : # The skeleton ID is okay to use pass if not new_skeleton : new_skeleton = ClassInstance ( ) new_skeleton . id = skeleton_id new_skeleton . user = user new_skeleton . project_id = project_id new_skeleton . class_column_id = class_map [ 'skeleton' ] if name is not None : new_skeleton . name = name else : new_skeleton . name = 'skeleton' new_skeleton . save ( ) new_skeleton . name = 'skeleton %d' % new_skeleton . id has_new_skeleton_id = new_skeleton . id is None new_skeleton . save ( ) skeleton_id = new_skeleton . id def relate_neuron_to_skeleton ( neuron , skeleton ) : return _create_relation ( user , project_id , relation_map [ 'model_of' ] , skeleton , neuron ) if not new_neuron : new_neuron = ClassInstance ( ) new_neuron . id = neuron_id create_neuron_skeleton_link = True new_neuron . user = user new_neuron . project_id = project_id new_neuron . class_column_id = class_map [ 'neuron' ] if name is not None : new_neuron . name = name elif neuron_id is None : # Don't override existing neuron names new_neuron . name = 'neuron' new_neuron . save ( ) new_neuron . name = 'neuron %d' % new_neuron . id has_new_neuron_id = new_neuron . id is None new_neuron . save ( ) neuron_id = new_neuron . id if create_neuron_skeleton_link : relate_neuron_to_skeleton ( neuron_id , new_skeleton . id ) # Add annotations, if that is requested. This will only by default append to # any existing annotations for this neuron (none for new neurons). If # replace_annotations is True, all existing annotations will be replaced. if replace_annotations : clear_annotations ( project_id , new_skeleton . id ) if annotations : annotation_map = { a : { 'user_id' : user . id } for a in annotations } _annotate_entities ( project_id , [ new_neuron . id ] , annotation_map ) # For pathological networks this can error, so do it before inserting # treenodes. root = find_root ( arborescence ) if root is None : raise ValueError ( 'No root, provided graph is malformed!' ) # Bulk create the required number of treenodes. This must be done in two # steps because treenode IDs are not known. cursor = connection . cursor ( ) cursor . execute ( """
          INSERT INTO treenode (project_id, location_x, location_y, location_z,
              editor_id, user_id, skeleton_id)
          SELECT t.project_id, t.x, t.x, t.x, t.user_id, t.user_id, t.skeleton_id
          FROM (VALUES (%(project_id)s, 0, %(user_id)s, %(skeleton_id)s))
              AS t (project_id, x, user_id, skeleton_id),
              generate_series(1, %(num_treenodes)s)
          RETURNING treenode.id
      """ , { 'project_id' : int ( project_id ) , 'user_id' : user . id , 'skeleton_id' : new_skeleton . id , 'num_treenodes' : arborescence . number_of_nodes ( ) } ) treenode_ids = cursor . fetchall ( ) # Flatten IDs treenode_ids = list ( chain . from_iterable ( treenode_ids ) ) nx . set_node_attributes ( arborescence , name = 'id' , values = dict ( zip ( arborescence . nodes ( ) , treenode_ids ) ) ) # Set parent node ID for n , nbrs in arborescence . adjacency ( ) : for nbr in nbrs : # FIXME: the cast here and below in the SQL (::bigint) shouldn't be # needed arborescence . nodes [ nbr ] [ 'parent_id' ] = int ( arborescence . nodes [ n ] [ 'id' ] ) if 'radius' not in arborescence . nodes [ nbr ] : arborescence . nodes [ nbr ] [ 'radius' ] = - 1 arborescence . nodes [ root ] [ 'parent_id' ] = None if 'radius' not in arborescence . nodes [ root ] : arborescence . nodes [ root ] [ 'radius' ] = - 1 new_location = tuple ( [ arborescence . nodes [ root ] [ k ] for k in ( 'x' , 'y' , 'z' ) ] ) if extended_data : treenode_template = '(' + '),(' . join ( '%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s' for _ in arborescence . nodes ) + ')' treenode_values = list ( chain . from_iterable ( [ d [ 'id' ] , d [ 'x' ] , d [ 'y' ] , d [ 'z' ] , d [ 'parent_id' ] , d [ 'radius' ] , d [ 'user_id' ] , d [ 'creation_time' ] , d [ 'editor_id' ] , d [ 'edition_time' ] , d [ 'confidence' ] ] for n , d in arborescence . nodes ( data = True ) ) ) # Include skeleton ID for index performance. cursor . execute ( f"""
              UPDATE treenode SET
                  location_x = v.x,
                  location_y = v.y,
                  location_z = v.z,
                  parent_id = v.parent_id::bigint,
                  radius = v.radius,
                  user_id = v.user_id,
                  creation_time = v.creation_time,
                  editor_id = v.editor_id,
                  edition_time = v.edition_time,
                  confidence = v.confidence
              FROM (VALUES {treenode_template}) AS v(id, x, y, z, parent_id,
                  radius, user_id, creation_time, editor_id, edition_time,
                  confidence)
              WHERE treenode.id = v.id
                  AND treenode.skeleton_id = %s
          """ , treenode_values + [ new_skeleton . id ] ) else : treenode_template = '(' + '),(' . join ( '%s,%s,%s,%s,%s,%s' for _ in arborescence . nodes ) + ')' treenode_values = list ( chain . from_iterable ( [ d [ 'id' ] , d [ 'x' ] , d [ 'y' ] , d [ 'z' ] , d [ 'parent_id' ] , d [ 'radius' ] ] for n , d in arborescence . nodes ( data = True ) ) ) # Include skeleton ID for index performance. cursor . execute ( f"""
              UPDATE treenode SET
                  location_x = v.x,
                  location_y = v.y,
                  location_z = v.z,
                  parent_id = v.parent_id,
                  radius = v.radius
              FROM (VALUES {treenode_template}) AS v(id, x, y, z, parent_id, radius)
              WHERE treenode.id = v.id
                  AND treenode.skeleton_id = %s
          """ , treenode_values + [ new_skeleton . id ] ) # Log import. annotation_info = f' {", ".join(annotations)}' if annotations else '' insert_into_log ( project_id , user . id , 'create_neuron' , new_location , f'Create neuron {new_neuron.id} and skeleton ' f'{new_skeleton.id} via import.{annotation_info}' ) # Store reference to source ID and source URL, if provided. if source_url and source_project_id : data_source = get_data_source ( project_id , source_url , source_project_id , user . id ) skeleton_origin = SkeletonOrigin . objects . create ( project_id = project_id , user_id = user . id , data_source = data_source , skeleton_id = new_skeleton . id , source_id = source_id , source_type = source_type ) if neuron_id or skeleton_id : # Reset ID sequence if IDs have been passed in. cursor . execute ( """
              SELECT setval('concept_id_seq', coalesce(max("id"), 1), max("id") IS NOT null)
              FROM concept;
              SELECT setval('location_id_seq', coalesce(max("id"), 1), max("id") IS NOT null)
              FROM location;
          """ ) return { 'neuron_id' : neuron_id , 'skeleton_id' : new_skeleton . id , 'graph' : arborescence , 'has_new_neuron_id' : has_new_neuron_id , 'has_new_skeleton_id' : has_new_skeleton_id , }