docs: def generate_assertion_edge_info(
      assertions: List[dict],
      orthologize_targets: List[str],
      bel_version: str,
      api_url: str,
      nanopub_type: str = "",
  ) -> dict:
      """Create edges (SRO) for assertions given orthologization targets
  
      Args:
          assertions: list of BEL statements (SRO object)
          orthologize_targets: list of species in TAX:<int> format
          bel_version: to be used for processing assertions
          api_url: BEL API url endpoint to use for terminologies and orthologies
      """
  
      bo = bel.lang.belobj.BEL(bel_version, api_url)
      bo_computed = bel.lang.belobj.BEL(bel_version, api_url)
  
      edge_info_list = []
  
      with utils.Timer() as t:
          for assertion in assertions:
              # if not assertion.get('relation', False):
              #     continue  # Skip any subject only statements
  
              start_time = t.elapsed
              bo.parse(assertion)
  
              if not bo.ast:
                  errors = [
                      f"{error[0]} {error[1]}"
                      for error in bo.validation_messages
                      if error[0] == "ERROR"
                  ]
                  edge_info = {"errors": copy.deepcopy(errors)}
                  edge_info_list.append(copy.deepcopy(edge_info))
                  continue
  
              # populate canonical terms and orthologs for assertion
              bo.collect_nsarg_norms()
              bo.collect_orthologs(orthologize_targets)
  
              log.info(
                  "Timing - time to collect nsargs and orthologs", delta_ms=(t.elapsed - start_time)
              )
  
              (edge_species_id, edge_species_label) = extract_ast_species(bo.ast)
              orig_species_id = edge_species_id
  
              canon = bo.canonicalize().to_triple()
  
              components = get_node_subcomponents(bo.ast)  # needs to be run after canonicalization
              computed_asts = bo.compute_edges(
                  ast_result=True
              )  # needs to be run after canonicalization
              decanon = bo.decanonicalize().to_triple()
  
              if nanopub_type == "backbone":
                  edge_types = ["backbone"]
              else:
                  edge_types = ["original", "primary"]
  
              if assertion.get("relation", False):
  
                  causal_edge_type = []
                  if "causal" in bo.spec["relations"]["info"][assertion["relation"]]["categories"]:
                      edge_types.append("causal")
  
                  edge_info = {
                      "edge_types": edge_types,
                      "species_id": edge_species_id,
                      "species_label": edge_species_label,
                      "canonical": canon,
                      "decanonical": decanon,
                      "subject_comp": components["subject_comp"],
                      "object_comp": components["object_comp"],
                      "errors": [],
                  }
                  edge_info_list.append(copy.deepcopy(edge_info))
  
              # Loop through primary computed asts
              for computed_ast in computed_asts:
                  bo_computed.ast = computed_ast
                  bo_computed.collect_nsarg_norms()
                  canon = bo_computed.canonicalize().to_triple()
                  components = get_node_subcomponents(
                      bo_computed.ast
                  )  # needs to be run after canonicalization
                  decanon = bo_computed.decanonicalize().to_triple()
  
                  (edge_species_id, edge_species_label) = extract_ast_species(bo_computed.ast)
  
                  edge_info = {
                      "edge_types": ["computed"],
                      "species_id": edge_species_id,
                      "species_label": edge_species_label,
                      "canonical": canon,
                      "decanonical": decanon,
                      "subject_comp": components["subject_comp"],
                      "object_comp": components["object_comp"],
                      "errors": [],
                  }
                  if [edge for edge in edge_info_list if edge.get("canonical", {}) == canon]:
                      continue  # skip if edge is already included (i.e. the primary is same as computed edge)
                  edge_info_list.append(copy.deepcopy(edge_info))
  
              # Skip orthologs if backbone nanopub
              if nanopub_type == "backbone":
                  continue
  
              # only process orthologs if there are species-specific NSArgs
              if len(bo.ast.species) > 0:
                  # Loop through orthologs
                  for species_id in orthologize_targets:
                      log.debug(f"Orig species: {orig_species_id}  Target species: {species_id}")
                      if species_id == orig_species_id:
                          continue
  
                      bo.orthologize(species_id)
  
                      (edge_species_id, edge_species_label) = extract_ast_species(bo.ast)
  
                      if edge_species_id == "None" or edge_species_id == orig_species_id:
                          log.debug(
                              f'Skipping orthologization- species == "None" or {orig_species_id}  ASTspecies: {bo.ast.species} for {bo}'
                          )
                          continue
  
                      ortho_decanon = bo.orthologize(
                          species_id
                      ).to_triple()  # defaults to decanonicalized orthologized form
                      ortho_canon = bo.canonicalize().to_triple()
                      computed_asts = bo.compute_edges(
                          ast_result=True
                      )  # needs to be run after canonicalization
                      components = get_node_subcomponents(
                          bo.ast
                      )  # needs to be run after canonicalization
  
                      if assertion.get("relation", False):
                          edge_info = {
                              "edge_types": ["orthologized", "primary"] + causal_edge_type,
                              "species_id": edge_species_id,
                              "species_label": edge_species_label,
                              "canonical": ortho_canon,
                              "decanonical": ortho_decanon,
                              "subject_comp": components["subject_comp"],
                              "object_comp": components["object_comp"],
                              "errors": [],
                          }
  
                          edge_info_list.append(copy.deepcopy(edge_info))
  
                      # Loop through orthologized computed asts
                      for computed_ast in computed_asts:
                          bo_computed.ast = computed_ast
                          bo_computed.collect_nsarg_norms()
                          canon = bo_computed.canonicalize().to_triple()
                          components = get_node_subcomponents(
                              bo_computed.ast
                          )  # needs to be run after canonicalization
                          decanon = bo_computed.decanonicalize().to_triple()
  
                          (edge_species_id, edge_species_label) = extract_ast_species(bo_computed.ast)
  
                          edge_info = {
                              "edge_types": ["computed", "orthologized"],
                              "species_id": edge_species_id,
                              "species_label": edge_species_label,
                              "canonical": canon,
                              "decanonical": decanon,
                              "subject_comp": components["subject_comp"],
                              "object_comp": components["object_comp"],
                              "errors": [],
                          }
                          if [edge for edge in edge_info_list if edge.get("canonical", {}) == canon]:
                              continue  # skip if edge is already included (i.e. the primary is same as computed edge)
                          edge_info_list.append(copy.deepcopy(edge_info))
  
      log.info("Timing - Generated all edge info for all nanopub assertions", delta_ms=t.elapsed)
  
      return {"edge_info_list": edge_info_list}