parameters: (request:HttpRequest, project_id=None)
return_statement: return JsonResponse({
          "links": links,
          "tags": tags
      }, safe=False)
docstring: Get connectors linked to a set of skeletons.
  
      The result data set includes information about linked connectors on a given
      input set of skeletons. These links are further constrained by relation
      type, with currently support available for: postsynaptic_to,
      presynaptic_to, abutting, gapjunction_with, tightjunction_with,
      desmosome_with.
  
      Returned is an object containing an array of links to connectors and a set
      of tags for all connectors found (if not disabled). The link array contains
      one array per connector link with the following content: [Linked skeleton ID,
      Connector ID, Connector X, Connector Y, Connector Z, Link confidence, Link
      creator ID, Linked treenode ID, Link edit time].
  
      A POST handler is able to accept large lists of skeleton IDs.
      ---
      parameters:
        - name: skeleton_ids
          description: Skeletons to list connectors for
          type: array
          items:
            type: integer
          paramType: form
          required: true
        - name: relation_type
          description: Relation of listed connector links
          type: string
          paramType: form
          required: true
        - name: with_tags
          description: If connector tags should be fetched
          type: boolean
          paramType: form
          defaultValue: true
          required: false
      type:
        links:
          type: array
          items:
            type: array
            items:
              type: string
          description: Matching connector links
          required: true
        tags:
           type array
docstring_summary: Get connectors linked to a set of skeletons.
docstring_tokens: Get connectors linked to a set of skeletons .
function: def list_connector_links(request:HttpRequest, project_id=None) -> JsonResponse:
      """Get connectors linked to a set of skeletons.
  
      The result data set includes information about linked connectors on a given
      input set of skeletons. These links are further constrained by relation
      type, with currently support available for: postsynaptic_to,
      presynaptic_to, abutting, gapjunction_with, tightjunction_with,
      desmosome_with.
  
      Returned is an object containing an array of links to connectors and a set
      of tags for all connectors found (if not disabled). The link array contains
      one array per connector link with the following content: [Linked skeleton ID,
      Connector ID, Connector X, Connector Y, Connector Z, Link confidence, Link
      creator ID, Linked treenode ID, Link edit time].
  
      A POST handler is able to accept large lists of skeleton IDs.
      ---
      parameters:
        - name: skeleton_ids
          description: Skeletons to list connectors for
          type: array
          items:
            type: integer
          paramType: form
          required: true
        - name: relation_type
          description: Relation of listed connector links
          type: string
          paramType: form
          required: true
        - name: with_tags
          description: If connector tags should be fetched
          type: boolean
          paramType: form
          defaultValue: true
          required: false
      type:
        links:
          type: array
          items:
            type: array
            items:
              type: string
          description: Matching connector links
          required: true
        tags:
           type array
      """
      data = request.POST if request.method == 'POST' else request.GET
      skeleton_ids = get_request_list(data, 'skeleton_ids', map_fn=int)
  
      if not skeleton_ids:
          raise ValueError("At least one skeleton ID required")
  
      relation_type = data.get('relation_type', 'presynaptic_to')
      with_tags = get_request_bool(data, 'with_tags', True)
  
      cursor = connection.cursor()
      relation_map = get_relation_to_id_map(project_id, cursor=cursor)
      relation_id = relation_map.get(relation_type)
      if not relation_id:
          raise ValueError("Unknown relation: " + relation_type)
      sk_template = ",".join(("(%s)",) * len(skeleton_ids))
  
      cursor.execute(f'''
          SELECT tc.skeleton_id, c.id, c.location_x, c.location_y, c.location_z,
                tc.confidence, tc.user_id, tc.treenode_id, tc.creation_time,
                tc.edition_time
          FROM treenode_connector tc
          JOIN (VALUES {sk_template}) q_skeleton(id)
              ON tc.skeleton_id = q_skeleton.id
          JOIN (VALUES (%s)) q_relation(id)
              ON tc.relation_id = q_relation.id
          JOIN connector c
              ON tc.connector_id = c.id
      ''', skeleton_ids + [relation_id])
  
      links = []
      for row in cursor.fetchall():
          lst = list(row)
          lst[8] = lst[8].isoformat()
          lst[9] = lst[9].isoformat()
          links.append(lst)
  
      connector_ids = [link[1] for link in links]
      tags:DefaultDict[Any, List] = defaultdict(list)
      if connector_ids and with_tags:
          c_template = ",".join(("(%s)",) * len(connector_ids))
          cursor.execute(f'''
              SELECT cci.connector_id, ci.name
              FROM connector_class_instance cci
              JOIN (VALUES {c_template}) q_connector(id)
                  ON cci.connector_id = q_connector.id
              JOIN (VALUES (%s)) q_relation(id)
                  ON cci.relation_id = q_relation.id
              JOIN class_instance ci
                  ON cci.class_instance_id = ci.id
          ''', connector_ids + [relation_map['labeled_as']])
  
          for row in cursor.fetchall():
              tags[row[0]].append(row[1])
  
          # Sort labels by name
          for connector_id, labels in tags.items():
              labels.sort(key=lambda k: k.upper())
  
      return JsonResponse({
          "links": links,
          "tags": tags
      }, safe=False)
function_tokens: def list_connector_links ( request : HttpRequest , project_id = None ) -> JsonResponse : data = request . POST if request . method == 'POST' else request . GET skeleton_ids = get_request_list ( data , 'skeleton_ids' , map_fn = int ) if not skeleton_ids : raise ValueError ( "At least one skeleton ID required" ) relation_type = data . get ( 'relation_type' , 'presynaptic_to' ) with_tags = get_request_bool ( data , 'with_tags' , True ) cursor = connection . cursor ( ) relation_map = get_relation_to_id_map ( project_id , cursor = cursor ) relation_id = relation_map . get ( relation_type ) if not relation_id : raise ValueError ( "Unknown relation: " + relation_type ) sk_template = "," . join ( ( "(%s)" , ) * len ( skeleton_ids ) ) cursor . execute ( f'''
          SELECT tc.skeleton_id, c.id, c.location_x, c.location_y, c.location_z,
                tc.confidence, tc.user_id, tc.treenode_id, tc.creation_time,
                tc.edition_time
          FROM treenode_connector tc
          JOIN (VALUES {sk_template}) q_skeleton(id)
              ON tc.skeleton_id = q_skeleton.id
          JOIN (VALUES (%s)) q_relation(id)
              ON tc.relation_id = q_relation.id
          JOIN connector c
              ON tc.connector_id = c.id
      ''' , skeleton_ids + [ relation_id ] ) links = [ ] for row in cursor . fetchall ( ) : lst = list ( row ) lst [ 8 ] = lst [ 8 ] . isoformat ( ) lst [ 9 ] = lst [ 9 ] . isoformat ( ) links . append ( lst ) connector_ids = [ link [ 1 ] for link in links ] tags : DefaultDict [ Any , List ] = defaultdict ( list ) if connector_ids and with_tags : c_template = "," . join ( ( "(%s)" , ) * len ( connector_ids ) ) cursor . execute ( f'''
              SELECT cci.connector_id, ci.name
              FROM connector_class_instance cci
              JOIN (VALUES {c_template}) q_connector(id)
                  ON cci.connector_id = q_connector.id
              JOIN (VALUES (%s)) q_relation(id)
                  ON cci.relation_id = q_relation.id
              JOIN class_instance ci
                  ON cci.class_instance_id = ci.id
          ''' , connector_ids + [ relation_map [ 'labeled_as' ] ] ) for row in cursor . fetchall ( ) : tags [ row [ 0 ] ] . append ( row [ 1 ] ) # Sort labels by name for connector_id , labels in tags . items ( ) : labels . sort ( key = lambda k : k . upper ( ) ) return JsonResponse ( { "links" : links , "tags" : tags } , safe = False )