NeKo lazily loads a cached reviewed-human UniProt table for gene-symbol and
accession translation. Unrecognized identifiers can use a bounded live UniProt
fallback; successful and failed lookups are memoized for the process.
deflooks_like_uniprot_accession(value:str)->bool:"""Return True if `value` matches the UniProt accession pattern."""returnbool(value)andbool(_RE_UNIPROT_ACCESSION.match(value))
Translate a gene symbol to its primary UniProt accession.
If label is not recognized as a gene symbol but already looks like a
valid UniProt accession, it is returned unchanged. Returns None if no
translation could be found.
defto_uniprot(label:str,organism:str=HUMAN_TAXON_ID)->str|None:""" Translate a gene symbol to its primary UniProt accession. If `label` is not recognized as a gene symbol but already looks like a valid UniProt accession, it is returned unchanged. Returns None if no translation could be found. """ifnotlabel:returnNone_ensure_loaded()accession=_state['symbol_to_uniprot'].get(label)ifaccession:returnaccession# Already looks like a UniProt accession (not a gene symbol): no need to# ask the live API to translate it as if it were one, just echo it back.iflooks_like_uniprot_accession(label):returnlabeliflabelin_state['symbol_fallback_cache']:return_state['symbol_fallback_cache'][label]dest='UniProtKB-Swiss-Prot'iforganism==HUMAN_TAXON_IDelse'UniProtKB'fallback=_fallback_translate({label},'Gene_Name',dest,organism)result=fallback.get(label)_state['symbol_fallback_cache'][label]=resultreturnresult
Translate a UniProt accession to its primary gene symbol.
If uniprot_id is not recognized as an accession but does not look like
one either (e.g. it is already a gene symbol), it is returned unchanged.
Returns None if no translation could be found.
defto_genesymbol(uniprot_id:str)->str|None:""" Translate a UniProt accession to its primary gene symbol. If `uniprot_id` is not recognized as an accession but does not look like one either (e.g. it is already a gene symbol), it is returned unchanged. Returns None if no translation could be found. """ifnotuniprot_id:returnNone_ensure_loaded()symbol=_state['uniprot_to_symbol'].get(uniprot_id)ifsymbol:returnsymbol# Does not look like a UniProt accession (presumably already a gene# symbol): no need to ask the live API to translate it as if it were# one, just echo it back.ifnotlooks_like_uniprot_accession(uniprot_id):returnuniprot_idifuniprot_idin_state['uniprot_fallback_cache']:return_state['uniprot_fallback_cache'][uniprot_id]fallback=_fallback_translate({uniprot_id},'UniProtKB_AC-ID','Gene_Name',None,)result=fallback.get(uniprot_id)_state['uniprot_fallback_cache'][uniprot_id]=resultreturnresult
defload_translated_dataframe(self,file_path:str):""" Loads a translated DataFrame from a file. Args: file_path (str): The path to the file containing the translated DataFrame. Returns: pd.DataFrame: The loaded DataFrame. """file_extension=os.path.splitext(file_path)[1].lower()iffile_extension=='.csv':self.df=pd.read_csv(file_path)eliffile_extensionin['.xls','.xlsx']:self.df=pd.read_excel(file_path)eliffile_extension=='.tsv':self.df=pd.read_csv(file_path,sep='\t')else:raiseValueError(f"Unsupported file format: {file_extension}")self.logger.info(f"Loaded translated DataFrame from {file_path}")
Translates a single identifier and updates the DataFrame if the translation is successful.
Args:
identifier (str): The identifier to translate.
source_type (str): The source type of the identifier.
dest_type (str): The destination type for the translation.
sleep_time (int): The time to wait (in seconds) for the request to complete.
replace_in_db (bool): Flag to decide if the translation should replace the original in the database.
file_path (str): Optional path to a file containing a pre-translated DataFrame to update.
deftranslate_single_identifier(self,identifier:str,source_type:str,dest_type:str,taxon_id:int=None,sleep_time:int=3,replace_in_db:bool=False,file_path:str=None):""" Translates a single identifier and updates the DataFrame if the translation is successful. Args: identifier (str): The identifier to translate. source_type (str): The source type of the identifier. dest_type (str): The destination type for the translation. sleep_time (int): The time to wait (in seconds) for the request to complete. replace_in_db (bool): Flag to decide if the translation should replace the original in the database. file_path (str): Optional path to a file containing a pre-translated DataFrame to update. Returns: List[str]: The translated identifiers. """iffile_path:self.load_translated_dataframe(file_path)translated_ids=[]forattemptinrange(self.max_retries):try:# Submit the request to the IdMappingClientifsource_type=='Gene_Name'andtaxon_id:request=IdMappingClient.submit(source=source_type,dest=dest_type,ids={identifier},taxon_id=taxon_id)else:request=IdMappingClient.submit(source=source_type,dest=dest_type,ids={identifier})# Wait for the request to completetime.sleep(sleep_time)# Process the resultresult=list(request.each_result())translated_ids=[m['to']forminresult]ifresultelse[]breakexceptExceptionase:ifattempt==self.max_retries-1:self.logger.error(f"Error processing {identifier} after {self.max_retries} attempts: {str(e)}")# Automatically select the first translationiftranslated_ids:translated_ids=[translated_ids[0]]# Print the translated entryprint(f"Original Identifier: {identifier}")print(f"Translated Identifier(s): {translated_idsiftranslated_idselse'No translation found'}")# Optionally replace the identifier in the DataFrameifreplace_in_dbandtranslated_ids:source_column=f"{self.columns[0]}_{dest_type}"target_column=f"{self.columns[1]}_{dest_type}"forcolumn,translated_columninzip(self.columns,[source_column,target_column]):self.df[translated_column]=self.df.apply(lambdarow:';'.join(translated_ids)ifrow[column]==identifierelserow[translated_column],axis=1)returntranslated_ids
defsave_translated_dataframe(self,file_path:str):""" Saves the translated DataFrame to a file. Args: file_path (str): The path where the translated DataFrame should be saved. """file_extension=os.path.splitext(file_path)[1].lower()iffile_extension=='.csv':self.df.to_csv(file_path,index=False)eliffile_extensionin['.xls','.xlsx']:self.df.to_excel(file_path,index=False)eliffile_extension=='.tsv':self.df.to_csv(file_path,sep='\t',index=False)else:raiseValueError(f"Unsupported file format: {file_extension}")self.logger.info(f"Translated DataFrame saved to {file_path}")