Copying Bio-python to globplot to satisfy the dependency
[jabaws.git] / binaries / src / globplot / biopython-1.50 / Bio / SeqUtils / IsoelectricPoint.py
1 # Copyright Yair Benita Y.Benita@pharm.uu.nl
2 # Biopython (http://biopython.org) license applies
3
4 """Calculate isoelectric points of polypeptides using methods of Bjellqvist.
5
6 pK values and the methos are taken from:
7
8 * Bjellqvist, B.,Hughes, G.J., Pasquali, Ch., Paquet, N., Ravier, F., Sanchez,
9 J.-Ch., Frutiger, S. & Hochstrasser, D.F.
10 The focusing positions of polypeptides in immobilized pH gradients can be predicted
11 from their amino acid sequences. Electrophoresis 1993, 14, 1023-1031. 
12
13 * Bjellqvist, B., Basse, B., Olsen, E. and Celis, J.E.
14 Reference points for comparisons of two-dimensional maps of proteins from
15 different human cell types defined in a pH scale where isoelectric points correlate
16 with polypeptide compositions. Electrophoresis 1994, 15, 529-539.
17
18 I designed the algorithm according to a note by David L. Tabb, available at:
19 http://fields.scripps.edu/DTASelect/20010710-pI-Algorithm.pdf
20
21 """
22
23 positive_pKs = { 'Nterm': 7.5, 'K': 10.0, 'R': 12.0, 'H':5.98 }
24 negative_pKs = { 'Cterm': 3.55, 'D': 4.05, 'E': 4.45, 'C':9.0, 'Y':10.0 }
25 pKcterminal= {'D':4.55, 'E':4.75}
26 pKnterminal = {'A':7.59, 'M':7.0, 'S':6.93, 'P':8.36, 'T':6.82, 'V':7.44, 'E':7.7}
27 charged_aas = ('K', 'R', 'H', 'D', 'E', 'C', 'Y')
28
29 # access this module through ProtParam.ProteinAnalysis class.
30 # first make a ProteinAnalysis object and then call its isoelectric_point method.
31 class IsoelectricPoint:
32     def __init__(self, ProteinSequence, AminoAcidsContent):
33         self.sequence = ProteinSequence        
34         self.charged_aas_content = self._select_charged(AminoAcidsContent)
35
36     # This function creates a dictionary with the contents of each charged aa, 
37     # plus Cterm and Nterm.
38     def _select_charged(self, AminoAcidsContent):
39         charged = {}    
40         for aa in charged_aas:
41             charged[aa] = float(AminoAcidsContent[aa])
42         charged['Nterm'] = 1.0
43         charged['Cterm'] = 1.0
44         return charged
45
46         #This function calculates the total charge of the protein at a given pH.                
47     def _chargeR(self, pH, pos_pKs, neg_pKs):
48         PositiveCharge = 0.0
49         for aa, pK in pos_pKs.iteritems():         
50              CR = 10**(pK-pH)
51              partial_charge = CR/(CR+1.0)
52              PositiveCharge += self.charged_aas_content[aa] * partial_charge 
53
54         NegativeCharge = 0.0
55         for aa, pK in neg_pKs.iteritems():         
56              CR = 10**(pH-pK)
57              partial_charge = CR/(CR+1.0)
58              NegativeCharge += self.charged_aas_content[aa] * partial_charge 
59
60         return PositiveCharge - NegativeCharge       
61         
62         # This is the action function, it tries different pH until the charge of the protein is 0 (or close).
63     def pi(self):        
64         pos_pKs = dict(positive_pKs)
65         neg_pKs = dict(negative_pKs)
66         nterm = self.sequence[0]
67         cterm = self.sequence[-1]    
68         if nterm in pKnterminal.keys():
69             pos_pKs['Nterm'] = pKnterminal[nterm]
70         if cterm in pKcterminal.keys():
71             neg_pKs['Cterm'] = pKcterminal[cterm]
72
73         # Bracket between pH1 and pH2
74         pH = 7.0
75         Charge = self._chargeR(pH, pos_pKs, neg_pKs)
76         if Charge > 0.0:
77             pH1 = pH
78             Charge1 = Charge
79             while Charge1 > 0.0:
80                 pH = pH1 + 1.0
81                 Charge = self._chargeR(pH, pos_pKs, neg_pKs)
82                 if Charge > 0.0:
83                     pH1 = pH
84                     Charge1 = Charge
85                 else:
86                     pH2 = pH
87                     Charge2 = Charge
88                     break
89         else:
90             pH2 = pH
91             Charge2 = Charge
92             while Charge2 < 0.0:
93                 pH = pH2 - 1.0
94                 Charge = self._chargeR(pH, pos_pKs, neg_pKs)
95                 if Charge < 0.0:
96                     pH2 = pH
97                     Charge2 = Charge
98                 else:
99                     pH1 = pH
100                     Charge1 = Charge
101                     break
102
103         # Bisection
104         while pH2 - pH1 > 0.0001 and Charge!=0.0:
105             pH = (pH1 + pH2) / 2.0
106             Charge = self._chargeR(pH, pos_pKs, neg_pKs)
107             if Charge > 0.0:
108                 pH1 = pH
109                 Charge1 = Charge
110             else:
111                 pH2 = pH
112                 Charge2 = Charge
113
114         return pH