Mercurial > repos > galaxyp > mqppep_preproc
view mqppep_mrgfltr.py @ 4:5c2beb4eb41c draft
planemo upload for repository https://github.com/galaxyproteomics/tools-galaxyp/tree/master/tools/mqppep commit 1c1dbc5a9838e5cd45724b6e53246eb80437e1f1
author | galaxyp |
---|---|
date | Tue, 14 Feb 2023 17:37:36 +0000 |
parents | b76c75521d91 |
children |
line wrap: on
line source
#!/usr/bin/env python # Import the packages needed import argparse import operator # for operator.itemgetter import os.path import re import shutil # for shutil.copyfile(src, dest) import sqlite3 as sql import sys # import the sys module for exc_info import time import traceback # for formatting stack-trace from codecs import getreader as cx_getreader import numpy as np import pandas # global constants N_A = "N/A" # ref: https://stackoverflow.com/a/8915613/15509512 # answers: "How to handle exceptions in a list comprehensions" # usage: # from math import log # eggs = [1,3,0,3,2] # print([x for x in [catch(log, egg) for egg in eggs] if x is not None]) # producing: # for <built-in function log> # with args (0,) # exception: math domain error # [0.0, 1.0986122886681098, 1.0986122886681098, 0.6931471805599453] def catch(func, *args, handle=lambda e: e, **kwargs): try: return func(*args, **kwargs) except Exception as e: print("For %s" % str(func)) print(" with args %s" % str(args)) print(" caught exception: %s" % str(e)) (ty, va, tb) = sys.exc_info() print(" stack trace: " + str(traceback.format_exception(ty, va, tb))) exit(-1) return None def whine(func, *args, handle=lambda e: e, **kwargs): try: return func(*args, **kwargs) except Exception as e: print("Warning: For %s" % str(func)) print(" with args %s" % str(args)) print(" caught exception: %s" % str(e)) (ty, va, tb) = sys.exc_info() print(" stack trace: " + str(traceback.format_exception(ty, va, tb))) return None def ppep_join(x): x = [i for i in x if N_A != i] result = "%s" % " | ".join(x) if result != "": return result else: return N_A def melt_join(x): tmp = {key.lower(): key for key in x} result = "%s" % " | ".join([tmp[key] for key in tmp]) return result def __main__(): # Parse Command Line parser = argparse.ArgumentParser( description="Phopsphoproteomic Enrichment Pipeline Merge and Filter." ) # inputs: # Phosphopeptide data for experimental results, including the intensities # and the mapping to kinase domains, in tabular format. parser.add_argument( "--phosphopeptides", "-p", nargs=1, required=True, dest="phosphopeptides", help=" ".join([ "Phosphopeptide data for experimental results, including the", "intensities and the mapping to kinase domains, in tabular format" ]), ) # UniProtKB/SwissProt DB input, SQLite parser.add_argument( "--ppep_mapping_db", "-d", nargs=1, required=True, dest="ppep_mapping_db", help="UniProtKB/SwissProt SQLite Database", ) # species to limit records chosed from PhosPhositesPlus parser.add_argument( "--species", "-x", nargs=1, required=False, default=[], dest="species", help=" ".join([ "limit PhosphoSitePlus records to indicated species", "(field may be empty)" ]), ) # outputs: # tabular output parser.add_argument( "--mrgfltr_tab", "-o", nargs=1, required=True, dest="mrgfltr_tab", help="Tabular output file for results", ) # CSV output parser.add_argument( "--mrgfltr_csv", "-c", nargs=1, required=True, dest="mrgfltr_csv", help="CSV output file for results", ) # SQLite output parser.add_argument( "--mrgfltr_sqlite", "-S", nargs=1, required=True, dest="mrgfltr_sqlite", help="SQLite output file for results", ) # "Make it so!" (parse the arguments) options = parser.parse_args() print("options: " + str(options)) # determine phosphopeptide ("upstream map") input tabular file access if options.phosphopeptides is None: exit('Argument "phosphopeptides" is required but not supplied') try: upstream_map_filename_tab = os.path.abspath(options.phosphopeptides[0]) input_file = open(upstream_map_filename_tab, "r") input_file.close() except Exception as e: exit("Error parsing phosphopeptides argument: %s" % str(e)) # determine input SQLite access if options.ppep_mapping_db is None: exit('Argument "ppep_mapping_db" is required but not supplied') try: uniprot_sqlite = os.path.abspath(options.ppep_mapping_db[0]) input_file = open(uniprot_sqlite, "rb") input_file.close() except Exception as e: exit("Error parsing ppep_mapping_db argument: %s" % str(e)) # copy input SQLite dataset to output SQLite dataset if options.mrgfltr_sqlite is None: exit('Argument "mrgfltr_sqlite" is required but not supplied') try: output_sqlite = os.path.abspath(options.mrgfltr_sqlite[0]) shutil.copyfile(uniprot_sqlite, output_sqlite) except Exception as e: exit("Error copying ppep_mapping_db to mrgfltr_sqlite: %s" % str(e)) # determine species to limit records from PSP_Regulatory_Sites if options.species is None: exit( 'Argument "species" is required (& may be empty) but not supplied' ) try: if len(options.species) > 0: species = options.species[0] else: species = "" except Exception as e: exit("Error parsing species argument: %s" % str(e)) # determine tabular output destination if options.mrgfltr_tab is None: exit('Argument "mrgfltr_tab" is required but not supplied') try: output_filename_tab = os.path.abspath(options.mrgfltr_tab[0]) output_file = open(output_filename_tab, "w") output_file.close() except Exception as e: exit("Error parsing mrgfltr_tab argument: %s" % str(e)) # determine CSV output destination if options.mrgfltr_csv is None: exit('Argument "mrgfltr_csv" is required but not supplied') try: output_filename_csv = os.path.abspath(options.mrgfltr_csv[0]) output_file = open(output_filename_csv, "w") output_file.close() except Exception as e: exit("Error parsing mrgfltr_csv argument: %s" % str(e)) def mqpep_getswissprot(): # # copied from Excel Output Script.ipynb BEGIN # # # String Constants ################# DEPHOSPHOPEP = "DephosphoPep" DESCRIPTION = "Description" FUNCTION_PHOSPHORESIDUE = ( "Function Phosphoresidue(PSP=PhosphoSitePlus.org)" ) # Gene Name from UniProtKB GENE_NAME = "Gene_Name" # ON_FUNCTION column from PSP_Regulatory_Sites ON_FUNCTION = ("ON_FUNCTION") # NOTES column from PSP_Regulatory_Sites ON_NOTES = "NOTES" # ON_OTHER_INTERACT column from PSP_Regulatory_Sites ON_OTHER_INTERACT = "ON_OTHER_INTERACT" # ON_PROCESS column from PSP_Regulatory_Sites ON_PROCESS = ("ON_PROCESS") # ON_PROT_INTERACT column from PSP_Regulatory_Sites ON_PROT_INTERACT = "ON_PROT_INTERACT" PHOSPHOPEPTIDE = "Phosphopeptide" PHOSPHOPEPTIDE_MATCH = "Phosphopeptide_match" PHOSPHORESIDUE = "Phosphoresidue" PUTATIVE_UPSTREAM_DOMAINS = " ".join([ "Putative Upstream Kinases(PSP=PhosphoSitePlus.org)/", "Phosphatases/Binding Domains" ]) SEQUENCE = "Sequence" SEQUENCE10 = "Sequence10" SEQUENCE7 = "Sequence7" SITE_PLUSMINUS_7AA_SQL = "SITE_PLUSMINUS_7AA" UNIPROT_ID = "UniProt_ID" UNIPROT_SEQ_AND_META_SQL = """ select Uniprot_ID, Description, Gene_Name, Sequence, Organism_Name, Organism_ID, PE, SV from UniProtKB order by Sequence, UniProt_ID """ UNIPROT_UNIQUE_SEQ_SQL = """ select distinct Sequence from UniProtKB group by Sequence """ PPEP_PEP_UNIPROTSEQ_SQL = """ select distinct phosphopeptide, peptide, sequence from uniprotkb_pep_ppep_view order by sequence """ PPEP_MELT_SQL = """ SELECT DISTINCT phospho_peptide AS 'p_peptide', kinase_map AS 'characterization', 'X' AS 'X' FROM ppep_gene_site_view """ # CREATE TABLE PSP_Regulatory_site ( # site_plusminus_7AA TEXT PRIMARY KEY ON CONFLICT IGNORE, # domain TEXT, # ON_FUNCTION TEXT, # ON_PROCESS TEXT, # ON_PROT_INTERACT TEXT, # ON_OTHER_INTERACT TEXT, # notes TEXT, # organism TEXT # ); PSP_REGSITE_SQL = """ SELECT DISTINCT SITE_PLUSMINUS_7AA , DOMAIN , ON_FUNCTION , ON_PROCESS , ON_PROT_INTERACT , ON_OTHER_INTERACT , NOTES , ORGANISM FROM PSP_Regulatory_site """ PPEP_ID_SQL = """ SELECT id AS 'ppep_id', seq AS 'ppep_seq' FROM ppep """ MRGFLTR_DDL = """ DROP VIEW IF EXISTS mrgfltr_metadata_view; DROP TABLE IF EXISTS mrgfltr_metadata; CREATE TABLE mrgfltr_metadata ( ppep_id INTEGER REFERENCES ppep(id) , Sequence10 TEXT , Sequence7 TEXT , GeneName TEXT , Phosphoresidue TEXT , UniProtID TEXT , Description TEXT , FunctionPhosphoresidue TEXT , PutativeUpstreamDomains TEXT , PRIMARY KEY (ppep_id) ON CONFLICT IGNORE ) ; CREATE VIEW mrgfltr_metadata_view AS SELECT DISTINCT ppep.seq AS phospho_peptide , Sequence10 , Sequence7 , GeneName , Phosphoresidue , UniProtID , Description , FunctionPhosphoresidue , PutativeUpstreamDomains FROM ppep, mrgfltr_metadata WHERE mrgfltr_metadata.ppep_id = ppep.id ORDER BY ppep.seq ; """ CITATION_INSERT_STMT = """ INSERT INTO Citation ( ObjectName, CitationData ) VALUES (?,?) """ CITATION_INSERT_PSP = " ".join([ "PhosphoSitePlus(R) (PSP) was created by Cell Signaling", "Technology Inc. It is licensed under a Creative Commons", "Attribution-NonCommercial-ShareAlike 3.0 Unported License.", "When using PSP data or analyses in printed publications or", "in online resources, the following acknowledgements must be", "included: (a) the words", '"PhosphoSitePlus(R), www.phosphosite.org" must', "be included at appropriate places in the text or webpage,", "and (b) the following citation must be included in the", 'bibliography: "Hornbeck PV, Zhang B, Murray B, Kornhauser', "JM, Latham V, Skrzypek E PhosphoSitePlus, 2014: mutations,", "PTMs and recalibrations. Nucleic Acids Res. 2015", '43:D512-20. PMID: 25514926."' ]) CITATION_INSERT_PSP_REF = " ".join([ 'Hornbeck, 2014, "PhosphoSitePlus, 2014: mutations, PTMs and', 'recalibrations.", https://pubmed.ncbi.nlm.nih.gov/22135298,', "https://doi.org/10.1093/nar/gkr1122" ]) MRGFLTR_METADATA_COLUMNS = [ "ppep_id", "Sequence10", "Sequence7", "GeneName", "Phosphoresidue", "UniProtID", "Description", "FunctionPhosphoresidue", "PutativeUpstreamDomains", ] # String Constants (end) ############ class Error(Exception): """Base class for exceptions in this module.""" pass class PreconditionError(Error): """Exception raised for errors in the input. Attributes: expression -- input expression in which the error occurred message -- explanation of the error """ def __init__(self, expression, message): self.expression = expression self.message = message # start_time = time.clock() #timer start_time = time.process_time() # timer # get keys from upstream tabular file using readline() # ref: https://stackoverflow.com/a/16713581/15509512 # answer to "Use codecs to read file with correct encoding" file1_encoded = open(upstream_map_filename_tab, "rb") file1 = cx_getreader("latin-1")(file1_encoded) count = 0 upstream_map_p_peptide_list = [] re_tab = re.compile("^[^\t]*") while True: count += 1 # Get next line from file line = file1.readline() # if line is empty # end of file is reached if not line: break if count > 1: m = re_tab.match(line) upstream_map_p_peptide_list.append(m[0]) file1.close() file1_encoded.close() # Get the list of phosphopeptides with the p's that represent # the phosphorylation sites removed re_phos = re.compile("p") end_time = time.process_time() # timer print( "%0.6f pre-read-SwissProt [0.1]" % (end_time - start_time,), file=sys.stderr, ) # -------- Get SwissProt data from SQLite database (start) ----------- # build UniProt sequence LUT and list of unique SwissProt sequences # Open SwissProt SQLite database conn = sql.connect(uniprot_sqlite) cur = conn.cursor() # Set up structures to hold SwissProt data uniprot_Sequence_List = [] UniProtSeqLUT = {} # Execute query for unique seqs without fetching the results yet uniprot_unique_seq_cur = cur.execute(UNIPROT_UNIQUE_SEQ_SQL) while 1: batch = uniprot_unique_seq_cur.fetchmany(size=50) if not batch: # handle case where no records are returned break for row in batch: Sequence = row[0] UniProtSeqLUT[(Sequence, DESCRIPTION)] = [] UniProtSeqLUT[(Sequence, GENE_NAME)] = [] UniProtSeqLUT[(Sequence, UNIPROT_ID)] = [] UniProtSeqLUT[Sequence] = [] # Execute query for seqs and metadata without fetching the results yet uniprot_seq_and_meta = cur.execute(UNIPROT_SEQ_AND_META_SQL) while 1: batch = uniprot_seq_and_meta.fetchmany(size=50) if not batch: # handle case where no records are returned break for ( UniProt_ID, Description, Gene_Name, Sequence, OS, OX, PE, SV, ) in batch: uniprot_Sequence_List.append(Sequence) UniProtSeqLUT[Sequence] = Sequence UniProtSeqLUT[(Sequence, UNIPROT_ID)].append(UniProt_ID) UniProtSeqLUT[(Sequence, GENE_NAME)].append(Gene_Name) if OS != N_A: Description += " OS=" + OS if OX != -1: Description += " OX=" + str(OX) if Gene_Name != N_A: Description += " GN=" + Gene_Name if PE != N_A: Description += " PE=" + PE if SV != N_A: Description += " SV=" + SV UniProtSeqLUT[(Sequence, DESCRIPTION)].append(Description) # Close SwissProt SQLite database; clean up local variables conn.close() Sequence = "" UniProt_ID = "" Description = "" Gene_Name = "" # -------- Get SwissProt data from SQLite database (finish) ----------- end_time = time.process_time() # timer print( "%0.6f post-read-SwissProt [0.2]" % (end_time - start_time,), file=sys.stderr, ) # -------- Get SwissProt data from SQLite database (start) ----------- # Open SwissProt SQLite database conn = sql.connect(uniprot_sqlite) cur = conn.cursor() # Set up dictionary to aggregate results for phosphopeptides # corresponding to dephosphoeptide DephosphoPep_UniProtSeq_LUT = {} # Set up dictionary to accumulate results PhosphoPep_UniProtSeq_LUT = {} # Execute query for tuples without fetching the results yet ppep_pep_uniprotseq_cur = cur.execute(PPEP_PEP_UNIPROTSEQ_SQL) while 1: batch = ppep_pep_uniprotseq_cur.fetchmany(size=50) if not batch: # handle case where no records are returned break for (phospho_pep, dephospho_pep, sequence) in batch: # do interesting stuff here... PhosphoPep_UniProtSeq_LUT[phospho_pep] = phospho_pep PhosphoPep_UniProtSeq_LUT[ (phospho_pep, DEPHOSPHOPEP) ] = dephospho_pep if dephospho_pep not in DephosphoPep_UniProtSeq_LUT: DephosphoPep_UniProtSeq_LUT[dephospho_pep] = set() DephosphoPep_UniProtSeq_LUT[ (dephospho_pep, DESCRIPTION) ] = [] DephosphoPep_UniProtSeq_LUT[ (dephospho_pep, GENE_NAME) ] = [] DephosphoPep_UniProtSeq_LUT[ (dephospho_pep, UNIPROT_ID) ] = [] DephosphoPep_UniProtSeq_LUT[(dephospho_pep, SEQUENCE)] = [] DephosphoPep_UniProtSeq_LUT[dephospho_pep].add(phospho_pep) if ( sequence not in DephosphoPep_UniProtSeq_LUT[ (dephospho_pep, SEQUENCE) ] ): DephosphoPep_UniProtSeq_LUT[ (dephospho_pep, SEQUENCE) ].append(sequence) for phospho_pep in DephosphoPep_UniProtSeq_LUT[dephospho_pep]: if phospho_pep != phospho_pep: print( "phospho_pep:'%s' phospho_pep:'%s'" % (phospho_pep, phospho_pep) ) if phospho_pep not in PhosphoPep_UniProtSeq_LUT: PhosphoPep_UniProtSeq_LUT[phospho_pep] = phospho_pep PhosphoPep_UniProtSeq_LUT[ (phospho_pep, DEPHOSPHOPEP) ] = dephospho_pep r = list( zip( [s for s in UniProtSeqLUT[(sequence, UNIPROT_ID)]], [s for s in UniProtSeqLUT[(sequence, GENE_NAME)]], [ s for s in UniProtSeqLUT[(sequence, DESCRIPTION)] ], ) ) # Sort by `UniProt_ID` # ref: https://stackoverflow.com/a/4174955/15509512 r = sorted(r, key=operator.itemgetter(0)) # Get one tuple for each `phospho_pep` # in DephosphoPep_UniProtSeq_LUT[dephospho_pep] for (upid, gn, desc) in r: # Append pseudo-tuple per UniProt_ID iff not present if ( upid not in DephosphoPep_UniProtSeq_LUT[ (dephospho_pep, UNIPROT_ID) ] ): DephosphoPep_UniProtSeq_LUT[ (dephospho_pep, UNIPROT_ID) ].append(upid) DephosphoPep_UniProtSeq_LUT[ (dephospho_pep, DESCRIPTION) ].append(desc) DephosphoPep_UniProtSeq_LUT[ (dephospho_pep, GENE_NAME) ].append(gn) # Close SwissProt SQLite database; clean up local variables conn.close() # wipe local variables phospho_pep = dephospho_pep = sequence = 0 upid = gn = desc = r = "" # -------- Get SwissProt data from SQLite database (finish) ----------- end_time = time.process_time() # timer print( "%0.6f finished reading and decoding '%s' [0.4]" % (end_time - start_time, upstream_map_filename_tab), file=sys.stderr, ) print( "{:>10} unique upstream phosphopeptides tested".format( str(len(upstream_map_p_peptide_list)) ) ) # Read in Upstream tabular file # We are discarding the intensity data; so read it as text upstream_data = pandas.read_table( upstream_map_filename_tab, dtype="str", index_col=0 ) end_time = time.process_time() # timer print( "%0.6f read Upstream Map from file [1g_1]" % (end_time - start_time,), file=sys.stderr, ) # timer upstream_data.index = upstream_map_p_peptide_list end_time = time.process_time() # timer print( "%0.6f added index to Upstream Map [1g_2]" % (end_time - start_time,), file=sys.stderr, ) # timer # trim upstream_data to include only the upstream map columns old_cols = upstream_data.columns.tolist() i = 0 first_intensity = -1 last_intensity = -1 intensity_re = re.compile("Intensity.*") for col_name in old_cols: m = intensity_re.match(col_name) if m: last_intensity = i if first_intensity == -1: first_intensity = i i += 1 # print('last intensity = %d' % last_intensity) col_PKCalpha = last_intensity + 2 data_in_cols = [old_cols[0]] + old_cols[ first_intensity - 1: last_intensity ] data_col_names = [old_cols[0]] + old_cols[ first_intensity: last_intensity + 1 ] if upstream_data.empty: print("upstream_data is empty") exit(0) data_in = upstream_data.copy(deep=True)[data_in_cols] data_in.columns = data_col_names print("data_in") print(data_in) ###################################################################### # Convert floating-point integers to int64 integers # ref: https://stackoverflow.com/a/68497603/15509512 data_in[list(data_in.columns[1:])] = ( data_in[list(data_in.columns[1:])] .astype("float64") .apply(np.int64) ) # create another phosphopeptide column that will be used to join later; # MAY need to change depending on Phosphopeptide column position # data_in[PHOSPHOPEPTIDE_MATCH] = data_in[data_in.columns.tolist()[0]] data_in[PHOSPHOPEPTIDE_MATCH] = data_in.index end_time = time.process_time() # timer print( "%0.6f set data_in[PHOSPHOPEPTIDE_MATCH] [A]" % (end_time - start_time,), file=sys.stderr, ) # timer # Produce a dictionary of metadata for a single phosphopeptide. # This is replaces `UniProtInfo_subdict` from the original code. def pseq_to_subdict(phospho_pep): # Strip "p" from phosphopeptide sequence dephospho_pep = re_phos.sub("", phospho_pep) # Determine number of phosphoresidues in phosphopeptide numps = len(phospho_pep) - len(dephospho_pep) # Determine location(s) of phosphoresidue(s) in phosphopeptide # (used later for Phosphoresidue, Sequence7, and Sequence10) ploc = [] # list of p locations i = 0 p = phospho_pep while i < numps: ploc.append(p.find("p")) p = p[: p.find("p")] + p[p.find("p") + 1:] i += 1 # Establish nested dictionary result = {} result[SEQUENCE] = [] result[UNIPROT_ID] = [] result[DESCRIPTION] = [] result[GENE_NAME] = [] result[PHOSPHORESIDUE] = [] result[SEQUENCE7] = [] result[SEQUENCE10] = [] # Add stripped sequence to dictionary result[SEQUENCE].append(dephospho_pep) # Locate phospho_pep in PhosphoPep_UniProtSeq_LUT # Caller may elect to: # try: # ... # except PreconditionError as pe: # print("'{expression}': {message}".format( # expression = pe.expression, # message = pe.message)) # ) # ) if phospho_pep not in PhosphoPep_UniProtSeq_LUT: raise PreconditionError( phospho_pep, " ".join([ "no matching phosphopeptide found in", "PhosphoPep_UniProtSeq_LUT" ]) ) if dephospho_pep not in DephosphoPep_UniProtSeq_LUT: raise PreconditionError( dephospho_pep, " ".join([ "dephosphorylated phosphopeptide not found", "in DephosphoPep_UniProtSeq_LUT" ]) ) if ( dephospho_pep != PhosphoPep_UniProtSeq_LUT[ (phospho_pep, DEPHOSPHOPEP)] ): my_err_msg = "dephosphorylated phosphopeptide does not match " my_err_msg += "PhosphoPep_UniProtSeq_LUT" my_err_msg += "[(phospho_pep,DEPHOSPHOPEP)] = " my_err_msg += PhosphoPep_UniProtSeq_LUT[ (phospho_pep, DEPHOSPHOPEP)] raise PreconditionError(dephospho_pep, my_err_msg) result[SEQUENCE] = [dephospho_pep] result[UNIPROT_ID] = DephosphoPep_UniProtSeq_LUT[ (dephospho_pep, UNIPROT_ID) ] result[DESCRIPTION] = DephosphoPep_UniProtSeq_LUT[ (dephospho_pep, DESCRIPTION) ] result[GENE_NAME] = DephosphoPep_UniProtSeq_LUT[ (dephospho_pep, GENE_NAME) ] if (dephospho_pep, SEQUENCE) not in DephosphoPep_UniProtSeq_LUT: raise PreconditionError( dephospho_pep, "".join( "no matching phosphopeptide found", "in DephosphoPep_UniProtSeq_LUT") ) UniProtSeqList = DephosphoPep_UniProtSeq_LUT[ (dephospho_pep, SEQUENCE) ] if len(UniProtSeqList) < 1: print( "Skipping DephosphoPep_UniProtSeq_LUT[('%s',SEQUENCE)] %s" % (dephospho_pep, "because value has zero length") ) for UniProtSeq in UniProtSeqList: i = 0 phosphoresidues = [] seq7s_set = set() seq7s = [] seq10s_set = set() seq10s = [] while i < len(ploc): start = UniProtSeq.find(dephospho_pep) # handle case where no sequence was found for dep-pep if start < 0: i += 1 continue psite = ( start + ploc[i] ) # location of phosphoresidue on protein sequence # add Phosphoresidue phosphosite = "p" + str(UniProtSeq)[psite] + str(psite + 1) phosphoresidues.append(phosphosite) # Add Sequence7 if psite < 7: # phospho_pep at N terminus seq7 = str(UniProtSeq)[: psite + 8] if seq7[psite] == "S": # if phosphosresidue is serine pres = "s" elif ( seq7[psite] == "T" ): # if phosphosresidue is threonine pres = "t" elif ( seq7[psite] == "Y" ): # if phosphoresidue is tyrosine pres = "y" else: # if not pSTY pres = "?" seq7 = ( seq7[:psite] + pres + seq7[psite + 1: psite + 8] ) while ( len(seq7) < 15 ): # add appropriate number of "_" to the front seq7 = "_" + seq7 elif ( len(UniProtSeq) - psite < 8 ): # phospho_pep at C terminus seq7 = str(UniProtSeq)[psite - 7:] if seq7[7] == "S": pres = "s" elif seq7[7] == "T": pres = "t" elif seq7[7] == "Y": pres = "y" else: pres = "?" seq7 = seq7[:7] + pres + seq7[8:] while ( len(seq7) < 15 ): # add appropriate number of "_" to the back seq7 = seq7 + "_" else: seq7 = str(UniProtSeq)[psite - 7: psite + 8] pres = "" # phosphoresidue if seq7[7] == "S": # if phosphosresidue is serine pres = "s" elif seq7[7] == "T": # if phosphosresidue is threonine pres = "t" elif seq7[7] == "Y": # if phosphoresidue is tyrosine pres = "y" else: # if not pSTY pres = "?" seq7 = seq7[:7] + pres + seq7[8:] if seq7 not in seq7s_set: seq7s.append(seq7) seq7s_set.add(seq7) # add Sequence10 if psite < 10: # phospho_pep at N terminus seq10 = ( str(UniProtSeq)[:psite] + "p" + str( UniProtSeq)[psite: psite + 11] ) elif ( len(UniProtSeq) - psite < 11 ): # phospho_pep at C terminus seq10 = ( str(UniProtSeq)[psite - 10: psite] + "p" + str( UniProtSeq)[psite:] ) else: seq10 = str(UniProtSeq)[psite - 10: psite + 11] seq10 = seq10[:10] + "p" + seq10[10:] if seq10 not in seq10s_set: seq10s.append(seq10) seq10s_set.add(seq10) i += 1 result[PHOSPHORESIDUE].append(phosphoresidues) result[SEQUENCE7].append(seq7s) # result[SEQUENCE10] is a list of lists of strings result[SEQUENCE10].append(seq10s) r = list( zip( result[UNIPROT_ID], result[GENE_NAME], result[DESCRIPTION], result[PHOSPHORESIDUE], ) ) # Sort by `UniProt_ID` # ref: https://stackoverflow.com//4174955/15509512 s = sorted(r, key=operator.itemgetter(0)) result[UNIPROT_ID] = [] result[GENE_NAME] = [] result[DESCRIPTION] = [] result[PHOSPHORESIDUE] = [] for r in s: result[UNIPROT_ID].append(r[0]) result[GENE_NAME].append(r[1]) result[DESCRIPTION].append(r[2]) result[PHOSPHORESIDUE].append(r[3]) # convert lists to strings in the dictionary for key, value in result.items(): if key not in [PHOSPHORESIDUE, SEQUENCE7, SEQUENCE10]: result[key] = "; ".join(map(str, value)) elif key in [SEQUENCE10]: # result[SEQUENCE10] is a list of lists of strings joined_value = "" joined_set = set() sep = "" for valL in value: # valL is a list of strings for val in valL: # val is a string if val not in joined_set: joined_set.add(val) joined_value += sep + val sep = "; " # joined_value is a string result[key] = joined_value newstring = "; ".join( [", ".join(prez) for prez in result[PHOSPHORESIDUE]] ) result[PHOSPHORESIDUE] = newstring # separate sequence7's by | oldstring = result[SEQUENCE7] oldlist = oldstring newstring = "" for ol in oldlist: for e in ol: if e == ";": newstring = newstring + " |" elif len(newstring) > 0 and 1 > newstring.count(e): newstring = newstring + " | " + e elif 1 > newstring.count(e): newstring = newstring + e result[SEQUENCE7] = newstring return [phospho_pep, result] # Construct list of [string, dictionary] lists # where the dictionary provides the SwissProt metadata # for a phosphopeptide result_list = [ whine(pseq_to_subdict, psequence) for psequence in data_in[PHOSPHOPEPTIDE_MATCH] ] end_time = time.process_time() # timer print( "%0.6f added SwissProt annotations to phosphopeptides [B]" % (end_time - start_time,), file=sys.stderr, ) # timer # Construct dictionary from list of lists # ref: https://www.8bitavenue.com/\ # how-to-convert-list-of-lists-to-dictionary-in-python/ UniProt_Info = { result[0]: result[1] for result in result_list if result is not None } end_time = time.process_time() # timer print( "%0.6f create dictionary mapping phosphopeptide %s" % (end_time - start_time, "to metadata dictionary [C]"), file=sys.stderr, ) # timer # cosmetic: add N_A to phosphopeptide rows with no hits p_peptide_list = [] for key in UniProt_Info: p_peptide_list.append(key) for nestedKey in UniProt_Info[key]: if UniProt_Info[key][nestedKey] == "": UniProt_Info[key][nestedKey] = N_A end_time = time.process_time() # timer print( "%0.6f performed cosmetic clean-up [D]" % (end_time - start_time,), file=sys.stderr, ) # timer # convert UniProt_Info dictionary to dataframe uniprot_df = pandas.DataFrame.transpose( pandas.DataFrame.from_dict(UniProt_Info) ) # reorder columns to match expected output file uniprot_df[ PHOSPHOPEPTIDE ] = uniprot_df.index # make index a column too cols = uniprot_df.columns.tolist() # cols = [cols[-1]]+cols[4:6]+[cols[1]]+[cols[2]]+[cols[6]]+[cols[0]] # uniprot_df = uniprot_df[cols] uniprot_df = uniprot_df[ [ PHOSPHOPEPTIDE, SEQUENCE10, SEQUENCE7, GENE_NAME, PHOSPHORESIDUE, UNIPROT_ID, DESCRIPTION, ] ] end_time = time.process_time() # timer print( "%0.6f reordered columns to match expected output file [1]" % (end_time - start_time,), file=sys.stderr, ) # timer # concat to split then groupby to collapse seq7_df = pandas.concat( [ pandas.Series(row[PHOSPHOPEPTIDE], row[SEQUENCE7].split(" | ")) for _, row in uniprot_df.iterrows() ] ).reset_index() seq7_df.columns = [SEQUENCE7, PHOSPHOPEPTIDE] # read in PhosphoSitePlus Regulatory Sites dataset from SQLite # --- -------------- begin read PSP_Regulatory_sites ----- conn = sql.connect(uniprot_sqlite) regsites_df = pandas.read_sql_query(PSP_REGSITE_SQL, conn) # Close SwissProt SQLite database conn.close() # ... -------------- end read PSP_Regulatory_sites ------- # keep only the human entries in dataframe if len(species) > 0: print( 'Limit PhosphoSitesPlus records to species "' + species + '"' ) regsites_df = regsites_df[regsites_df.ORGANISM == species] # merge the seq7 df with the regsites df based off of the sequence7 merge_df = seq7_df.merge( regsites_df, left_on=SEQUENCE7, right_on=SITE_PLUSMINUS_7AA_SQL, how="left", ) # after merging df, select only the columns of interest; # note that PROTEIN is absent here merge_df = merge_df[ [ PHOSPHOPEPTIDE, SEQUENCE7, ON_FUNCTION, ON_PROCESS, ON_PROT_INTERACT, ON_OTHER_INTERACT, ON_NOTES, ] ] # combine column values of interest # into one FUNCTION_PHOSPHORESIDUE column" merge_df[FUNCTION_PHOSPHORESIDUE] = merge_df[ON_FUNCTION].str.cat( merge_df[ON_PROCESS], sep="; ", na_rep="" ) merge_df[FUNCTION_PHOSPHORESIDUE] = merge_df[ FUNCTION_PHOSPHORESIDUE ].str.cat(merge_df[ON_PROT_INTERACT], sep="; ", na_rep="") merge_df[FUNCTION_PHOSPHORESIDUE] = merge_df[ FUNCTION_PHOSPHORESIDUE ].str.cat(merge_df[ON_OTHER_INTERACT], sep="; ", na_rep="") merge_df[FUNCTION_PHOSPHORESIDUE] = merge_df[ FUNCTION_PHOSPHORESIDUE ].str.cat(merge_df[ON_NOTES], sep="; ", na_rep="") # remove the columns that were combined merge_df = merge_df[ [PHOSPHOPEPTIDE, SEQUENCE7, FUNCTION_PHOSPHORESIDUE] ] end_time = time.process_time() # timer print( "%0.6f merge regsite metadata [1a]" % (end_time - start_time,), file=sys.stderr, ) # timer # cosmetic changes to Function Phosphoresidue column fp_series = pandas.Series(merge_df[FUNCTION_PHOSPHORESIDUE]) end_time = time.process_time() # timer print( "%0.6f more cosmetic changes [1b]" % (end_time - start_time,), file=sys.stderr, ) # timer i = 0 while i < len(fp_series): # remove the extra ";" so that it looks more professional if fp_series[i] == "; ; ; ; ": # remove ; from empty hits fp_series[i] = "" while fp_series[i].endswith("; "): # remove ; from the ends fp_series[i] = fp_series[i][:-2] while fp_series[i].startswith("; "): # remove ; from the beginning fp_series[i] = fp_series[i][2:] fp_series[i] = fp_series[i].replace("; ; ; ; ", "; ") fp_series[i] = fp_series[i].replace("; ; ; ", "; ") fp_series[i] = fp_series[i].replace("; ; ", "; ") # turn blanks into N_A to signify the info # that was searched for but cannot be found if fp_series[i] == "": fp_series[i] = N_A i += 1 merge_df[FUNCTION_PHOSPHORESIDUE] = fp_series end_time = time.process_time() # timer print( "%0.6f cleaned up semicolons [1c]" % (end_time - start_time,), file=sys.stderr, ) # timer # merge uniprot df with merge df uniprot_regsites_merged_df = uniprot_df.merge( merge_df, left_on=PHOSPHOPEPTIDE, right_on=PHOSPHOPEPTIDE, how="left", ) # collapse the merged df uniprot_regsites_collapsed_df = pandas.DataFrame( uniprot_regsites_merged_df.groupby(PHOSPHOPEPTIDE)[ FUNCTION_PHOSPHORESIDUE ].apply(lambda x: ppep_join(x)) ) # .apply(lambda x: "%s" % ' | '.join(x))) end_time = time.process_time() # timer print( "%0.6f collapsed pandas dataframe [1d]" % (end_time - start_time,), file=sys.stderr, ) # timer uniprot_regsites_collapsed_df[ PHOSPHOPEPTIDE ] = ( uniprot_regsites_collapsed_df.index ) # add df index as its own column # rename columns uniprot_regsites_collapsed_df.columns = [ FUNCTION_PHOSPHORESIDUE, "ppp", ] end_time = time.process_time() # timer print( "%0.6f selected columns to be merged to uniprot_df [1e]" % (end_time - start_time,), file=sys.stderr, ) # timer # add columns based on Sequence7 matching site_+/-7_AA uniprot_regsite_df = pandas.merge( left=uniprot_df, right=uniprot_regsites_collapsed_df, how="left", left_on=PHOSPHOPEPTIDE, right_on="ppp", ) end_time = time.process_time() # timer print( "%0.6f added columns based on Sequence7 matching site_+/-7_AA [1f]" % (end_time - start_time,), file=sys.stderr, ) # timer data_in.rename( {"Protein description": PHOSPHOPEPTIDE}, axis="columns", inplace=True, ) res2 = sorted( data_in[PHOSPHOPEPTIDE_MATCH].tolist(), key=lambda s: s.casefold() ) data_in = data_in.loc[res2] end_time = time.process_time() # timer print( "%0.6f sorting time [1f]" % (end_time - start_time,), file=sys.stderr, ) # timer print("old_cols[:col_PKCalpha]") print(old_cols[:col_PKCalpha]) cols = [old_cols[0]] + old_cols[col_PKCalpha - 1:] upstream_data = upstream_data[cols] print("upstream_data.columns") print(upstream_data.columns) end_time = time.process_time() # timer print( "%0.6f refactored columns for Upstream Map [1g]" % (end_time - start_time,), file=sys.stderr, ) # timer # rename upstream columns in new list def col_rename(name): if "_NetworKIN" in name: name = name.split("_")[0] if " motif" in name: name = name.split(" motif")[0] if " sequence " in name: name = name.split(" sequence")[0] if "_Phosida" in name: name = name.split("_")[0] if "_PhosphoSite" in name: name = name.split("_")[0] return name new_cols = [col_rename(col) for col in cols] upstream_data.columns = new_cols end_time = time.process_time() # timer print( "%0.6f renamed columns for Upstream Map [1h_1]" % (end_time - start_time,), file=sys.stderr, ) # timer # Create upstream_data_cast as a copy of upstream_data # but with first column substituted by the phosphopeptide sequence upstream_data_cast = upstream_data.copy() new_cols_cast = new_cols new_cols_cast[0] = "p_peptide" upstream_data_cast.columns = new_cols_cast upstream_data_cast["p_peptide"] = upstream_data.index # Get melted kinase mapping data from SQLite database # --- begin read upstream_data_melt --------------------------------- conn = sql.connect(uniprot_sqlite) upstream_data_melt_df = pandas.read_sql_query(PPEP_MELT_SQL, conn) # Close SwissProt SQLite database conn.close() upstream_data_melt = upstream_data_melt_df.copy() upstream_data_melt.columns = ["p_peptide", "characterization", "X"] upstream_data_melt["characterization"] = [ col_rename(s) for s in upstream_data_melt["characterization"] ] print( "%0.6f upstream_data_melt_df initially has %d rows" % (end_time - start_time, len(upstream_data_melt.axes[0])), file=sys.stderr, ) # ref: https://stackoverflow.com/a/27360130/15509512 # e.g. df.drop(df[df.score < 50].index, inplace=True) upstream_data_melt.drop( upstream_data_melt[upstream_data_melt.X != "X"].index, inplace=True ) print( "%0.6f upstream_data_melt_df pre-dedup has %d rows" % (end_time - start_time, len(upstream_data_melt.axes[0])), file=sys.stderr, ) # ... end read upstream_data_melt --------------------------------- end_time = time.process_time() # timer print( "%0.6f melted and minimized Upstream Map dataframe [1h_2]" % (end_time - start_time,), file=sys.stderr, ) # timer # ... end read upstream_data_melt end_time = time.process_time() # timer print( "%0.6f indexed melted Upstream Map [1h_2a]" % (end_time - start_time,), file=sys.stderr, ) # timer upstream_delta_melt_LoL = upstream_data_melt.values.tolist() melt_dict = {} for key in upstream_map_p_peptide_list: melt_dict[key] = [] for el in upstream_delta_melt_LoL: (p_peptide, characterization, X) = tuple(el) if p_peptide in melt_dict: melt_dict[p_peptide].append(characterization) else: los = [ "Phosphopeptide %s" % p_peptide, "not found in ppep_mapping_db:", '"phopsphopeptides" and "ppep_mapping_db" must both', "originate from the same run of mqppep_kinase_mapping" ] exit(" ".join(los)) end_time = time.process_time() # timer print( "%0.6f appended peptide characterizations [1h_2b]" % (end_time - start_time,), file=sys.stderr, ) # timer # for key in upstream_map_p_peptide_list: # melt_dict[key] = ' | '.join(melt_dict[key]) for key in upstream_map_p_peptide_list: melt_dict[key] = melt_join(melt_dict[key]) end_time = time.process_time() # timer print( "%0.6f concatenated multiple characterizations [1h_2c]" % (end_time - start_time,), file=sys.stderr, ) # timer # map_dict is a dictionary of dictionaries map_dict = {} for key in upstream_map_p_peptide_list: map_dict[key] = {} map_dict[key][PUTATIVE_UPSTREAM_DOMAINS] = melt_dict[key] end_time = time.process_time() # timer print( "%0.6f instantiated map dictionary [2]" % (end_time - start_time,), file=sys.stderr, ) # timer # convert map_dict to dataframe map_df = pandas.DataFrame.transpose( pandas.DataFrame.from_dict(map_dict) ) map_df["p-peptide"] = map_df.index # make index a column too cols_map_df = map_df.columns.tolist() cols_map_df = [cols_map_df[1]] + [cols_map_df[0]] map_df = map_df[cols_map_df] # join map_df to uniprot_regsite_df output_df = uniprot_regsite_df.merge( map_df, how="left", left_on=PHOSPHOPEPTIDE, right_on="p-peptide" ) output_df = output_df[ [ PHOSPHOPEPTIDE, SEQUENCE10, SEQUENCE7, GENE_NAME, PHOSPHORESIDUE, UNIPROT_ID, DESCRIPTION, FUNCTION_PHOSPHORESIDUE, PUTATIVE_UPSTREAM_DOMAINS, ] ] # join output_df back to quantitative columns in data_in df quant_cols = data_in.columns.tolist() quant_cols = quant_cols[1:] quant_data = data_in[quant_cols] # ---- Write merge/filter metadata to SQLite database (start) ---- # Open SwissProt SQLite database conn = sql.connect(output_sqlite) cur = conn.cursor() cur.executescript(MRGFLTR_DDL) cur.execute( CITATION_INSERT_STMT, ("mrgfltr_metadata_view", CITATION_INSERT_PSP), ) cur.execute( CITATION_INSERT_STMT, ("mrgfltr_metadata", CITATION_INSERT_PSP) ) cur.execute( CITATION_INSERT_STMT, ("mrgfltr_metadata_view", CITATION_INSERT_PSP_REF), ) cur.execute( CITATION_INSERT_STMT, ("mrgfltr_metadata", CITATION_INSERT_PSP_REF) ) # Read ppep-to-sequence LUT ppep_lut_df = pandas.read_sql_query(PPEP_ID_SQL, conn) # write only metadata for merged/filtered records to SQLite mrgfltr_metadata_df = output_df.copy() # replace phosphopeptide seq with ppep.id mrgfltr_metadata_df = ppep_lut_df.merge( mrgfltr_metadata_df, left_on="ppep_seq", right_on=PHOSPHOPEPTIDE, how="inner", ) mrgfltr_metadata_df.drop( columns=[PHOSPHOPEPTIDE, "ppep_seq"], inplace=True ) # rename columns mrgfltr_metadata_df.columns = MRGFLTR_METADATA_COLUMNS mrgfltr_metadata_df.to_sql( "mrgfltr_metadata", con=conn, if_exists="append", index=False, method="multi", ) # Close SwissProt SQLite database conn.close() # ---- Write merge/filter metadata to SQLite database (finish) ---- output_df = output_df.merge( quant_data, how="right", left_on=PHOSPHOPEPTIDE, right_on=PHOSPHOPEPTIDE_MATCH, ) output_cols = output_df.columns.tolist() output_cols = output_cols[:-1] output_df = output_df[output_cols] # cosmetic changes to Upstream column # fill the NaN with "" for those Phosphopeptides that got a # "WARNING: Failed match for " in the upstream mapping output_df[PUTATIVE_UPSTREAM_DOMAINS] = output_df[ PUTATIVE_UPSTREAM_DOMAINS ].fillna( "" ) us_series = pandas.Series(output_df[PUTATIVE_UPSTREAM_DOMAINS]) i = 0 while i < len(us_series): # turn blanks into N_A to signify the info # that was searched for but cannot be found if us_series[i] == "": us_series[i] = N_A i += 1 output_df[PUTATIVE_UPSTREAM_DOMAINS] = us_series end_time = time.process_time() # timer print( "%0.6f establisheed output [3]" % (end_time - start_time,), file=sys.stderr, ) # timer (output_rows, output_cols) = output_df.shape output_df = output_df.convert_dtypes(convert_integer=True) # Output onto Final CSV file output_df.to_csv(output_filename_csv, index=False) output_df.to_csv( output_filename_tab, quoting=None, sep="\t", index=False ) end_time = time.process_time() # timer print( "%0.6f wrote output [4]" % (end_time - start_time,), file=sys.stderr, ) # timer print( "{:>10} phosphopeptides written to output".format(str(output_rows)) ) end_time = time.process_time() # timer print( "%0.6f seconds of non-system CPU time were consumed" % (end_time - start_time,), file=sys.stderr, ) # timer # Rev. 7/1/2016 # Rev. 7/3/2016 : fill NaN in Upstream column to replace to N/A's # Rev. 7/3/2016: renamed Upstream column to PUTATIVE_UPSTREAM_DOMAINS # Rev. 12/2/2021: Converted to Python from ipynb; use fast \ # Aho-Corasick searching; \ # read from SwissProt SQLite database # Rev. 12/9/2021: Transfer code to Galaxy tool wrapper # # copied from Excel Output Script.ipynb END # # try: catch( mqpep_getswissprot, ) exit(0) except Exception as e: exit("Internal error running mqpep_getswissprot(): %s" % (e)) if __name__ == "__main__": __main__()