Source code for acore.io.uniprot

"""Uniprot API user functions for fetching annotations for UniProt IDs and providing
the results as a pandas.DataFrame."""

import pandas as pd

from .uniprot import (
    check_id_mapping_results_ready,
    get_id_mapping_results_link,
    get_id_mapping_results_search,
    submit_id_mapping,
)


# function for outside usage
[docs] def fetch_annotations( ids: pd.Index | list, fields: str = "accession,go_p,go_c,go_f", ) -> pd.DataFrame: """Fetch annotations for UniProt IDs. Combines several calls to the API of UniProt's knowledgebase (KB). Parameters ---------- ids : pd.Index | list Iterable of UniProt IDs. Fetches annotations as speecified by the specified fields. fields : str, optional Fields to fetch, by default "accession,go_p,go_c. See for availble fields: https://www.uniprot.org/help/return_fields Returns ------- pd.DataFrame DataFrame with annotations of the UniProt IDs. """ job_id = submit_id_mapping(from_db="UniProtKB_AC-ID", to_db="UniProtKB", ids=ids) # tsv used here to return a DataFrame. Maybe other formats are availale at some points _format = "tsv" if check_id_mapping_results_ready(job_id): link = get_id_mapping_results_link(job_id) # add fields to the link to get more information # From and Entry (accession) are the same for UniProt IDs. results = get_id_mapping_results_search( link + f"?fields={fields}&format={_format}" ) header = results.pop(0).split("\t") results = [line.split("\t") for line in results] df = pd.DataFrame(results, columns=header) return df
[docs] def process_annotations(annotations: pd.DataFrame, fields: str) -> pd.DataFrame: """Process annotations fetched from UniProt API. Parameters ---------- annotations : pd.DataFrame DataFrame with annotations fetched from UniProt API. fields : str Fields that were fetched from the API. Comma-separated string. Fields needs to match number of columns in annotations. Returns ------- pd.DataFrame Processed DataFrame with annotations in long-format. """ d_fields_to_col = { k: v for k, v in zip(fields.split(","), annotations.columns[1:], strict=True) } # expand go terms to_expand = list() for field in d_fields_to_col: if "go_" in field: col = d_fields_to_col[field] annotations[col] = annotations[col].str.split(";") to_expand.append(col) for col in to_expand: # this is a bit wastefull. Processing to stack format should be done here. annotations = annotations.explode(col, ignore_index=True) # process other than go term columns annotations = ( annotations.set_index("From") .rename_axis("identifier") # .drop("Entry", axis=1) .rename_axis("source", axis=1) .stack() .to_frame("annotation") .reset_index() .drop_duplicates(ignore_index=True) .replace("", pd.NA) .dropna() ) return annotations