<p>A few additional hints that may help clarify the algorithm:</p>
<p>The <code>20</code> magic number is because there are twenty amino acids.  The <code>400</code> magic number is because there are <code>20 * 20</code> potential dipeptides.</p>
<p>These peptides are then hashed by converting their letter to a number in the range [0, 20). You can then multiple one of them by 20 and add the other to get a number between [0, 400).  In the case of this function the first amino acid &quot;code&quot; is multiplied by 20. This number can be converted back to the dipeptide sequence when outputting the data.  The translation table they use is generated here <code>diPeptides = [aa1 + aa2 for aa1 in AA for aa2 in AA]</code>.</p>
<p>The nested loops are to loop through each entry and then each sequence to get every dipeptide sequence, which can be done in linear time.</p>
<p>Just as a quick note on hashing DNA and peptide sequences.  You can generally convert them to an array index by using increasing powers of the alphabet size multiplied by the letter index of the alphabet.  For example, for DNA you can convert <code>A=0, C=1, G=2, T=3</code>, and you can hash fourmers by using <code>4^4 * a[i] + 4^3 * a[i + 1] + 4^2 * a[i + 2] + 4^1 * a[i + 3]</code>. In code you may see this performed with bitshifts for DNA since the alphabet size is a power of 2.</p>
<p>The advantage of this hashing scheme is. thateach sequence is guaranteed to have a unique index.  The problem with this method is that as if you wish to use longer k-mers the memory usage will grow exponentially.  For example, for 16-mers you need 4 billion combinations, which is the size of a 32 bit unsigned integer.</p>

CC BY-SA 4.0
2021-09-11T15:27:57.363Z
Thank you so much. I am trying to follow what your suggestion. I am getting all sorts of error messages. I have very little programming skills. I only learnt to work with python on jupyter notebook. This toolkit (or any toolkit, I presume). works across multiple files at a time I presume. I am completely lost.
Noob
CC BY-SA 4.0
2021-09-11T15:30:09.020Z
I have understood the concept of hashing i.e. `AADict={'A': 0,  'C': 1,  'D': 2, 'E': 3, 'F': 4, 'G': 5, 'H': 6, 'I': 7, 'K': 8, 'L': 9, 'M': 10, 'N': 11, 'P': 12, 'Q': 13, 'R': 14, 'S': 15, 'T': 16, 'V': 17, 'W': 18, 'Y': 19}`
Noob
CC BY-SA 4.0
2021-09-11T15:49:35.860Z
I understood multiplying one of them by 20 and add the other to get a number between [0, 400). But still these 2 line ```if sum(tmpCode) != 0:             tmpCode = [i/sum(tmpCode) for i in tmpCode]``` are really bothering me
Noob
CC BY-SA 4.0
2021-09-11T21:25:27.957Z
They are checking if the sum is larger than zero.  Then they are normalizing the totals to sum to 1.0; ie. calculating the frequency of each dipeptide.
GWW
CC BY-SA 4.0
2021-09-12T12:07:34.643Z
It's working now. Thank you so much. I really appreciate
Noob
CC BY-SA 4.0
2021-09-11T15:00:09.310Z
2021-09-11T15:18:02.433Z
2021-09-11T15:18:02.433Z
GWW
<p>Dipeptide composition of a protein sequence is the number of times a particular dipeptide (e.g. Arginine-Histidine) occurs in a sequence divided by the total number of dipeptides in the sequence (which is the length of the sequence - 1)</p>
<p>I have found the following code for this:</p>
<pre><code>import re

def DPC(fastas):
    AA = 'ACDEFGHIKLMNPQRSTVWY'
    encodings = []
    diPeptides = [aa1 + aa2 for aa1 in AA for aa2 in AA]
    header = ['#'] + diPeptides
    encodings.append(header)

    AADict = {}
    for i in range(len(AA)):
        AADict[AA[i]] = i

    for i in fastas:
        name, sequence = i[0], re.sub('-', '', i[1])
        code = [name]
        tmpCode = [0] * 400
        for j in range(len(sequence) - 2 + 1):
            tmpCode[AADict[sequence[j]] * 20 + AADict[sequence[j+1]]] = tmpCode[AADict[sequence[j]] * 20 + AADict[sequence[j+1]]] +1
        if sum(tmpCode) != 0:
            tmpCode = [i/sum(tmpCode) for i in tmpCode]
        code = code + tmpCode
        encodings.append(code)
    return encodings
</code></pre>
<p>There is another file (main) from where the arguments <code>fastas</code> come from which is basically a list of strings where every string is a protein sequence. I am finding it really difficult to understand the nested loops that were used:</p>
<pre><code>    for i in fastas:
        name, sequence = i[0], re.sub('-', '', i[1])
        code = [name]
        tmpCode = [0] * 400
        for j in range(len(sequence) - 2 + 1):
            tmpCode[AADict[sequence[j]] * 20 + AADict[sequence[j+1]]] = tmpCode[AADict[sequence[j]] * 20 + AADict[sequence[j+1]]] +1
        if sum(tmpCode) != 0:
            tmpCode = [i/sum(tmpCode) for i in tmpCode]
        code = code + tmpCode
        encodings.append(code)
</code></pre>
<p>I have spent 4-5 hours on this but I am still finding it really difficult to follow. I would really appreciate if anyone can explain the steps involved in these loops. Thank you!</p>
<p><strong>Edit</strong>: The github link to the files are :</p>
<ol>
<li><a href="https://github.com/Superzchen/iFeature/blob/master/codes/DPC.py" rel="nofollow noreferrer">DPC.py</a></li>
<li><a href="https://github.com/Superzchen/iFeature/blob/master/iFeature.py" rel="nofollow noreferrer">iFeature.py</a></li>
</ol>
<p>The github link to the python toolkit: <a href="https://github.com/Superzchen/iFeature" rel="nofollow noreferrer">iFeature</a></p>

CC BY-SA 4.0
2021-09-11T14:50:06.237Z
One thing that may help when trying to understand other peoples code is to add print statements and possibly break statements at various parts of the code.  You can print out exactly what is happening in the loop; for example, in the nested loop print j, print the tmpCode index, print the value at the tmp code etc.
GWW
CC BY-SA 4.0
2021-09-12T12:06:16.600Z
@user438383, deleted
Noob
<python><featurecounts>
Help to understand the code for dipeptide composition calculation (in python)
# Help to understand the code for dipeptide composition calculation (in python)

(Asked by: username_0 on 2021-09-11)

Dipeptide composition of a protein sequence is the number of times a particular dipeptide (e.g. Arginine-Histidine) occurs in a sequence divided by the total number of dipeptides in the sequence (which is the length of the sequence - 1)
I have found the following code for this:
import re

def DPC(fastas):
    AA = 'ACDEFGHIKLMNPQRSTVWY'
    encodings = []
    diPeptides = [aa1 + aa2 for aa1 in AA for aa2 in AA]
    header = ['#'] + diPeptides
    encodings.append(header)

    AADict = {}
    for i in range(len(AA)):
        AADict[AA[i]] = i

    for i in fastas:
        name, sequence = i[0], re.sub('-', '', i[1])
        code = [name]
        tmpCode = [0] * 400
        for j in range(len(sequence) - 2 + 1):
            tmpCode[AADict[sequence[j]] * 20 + AADict[sequence[j+1]]] = tmpCode[AADict[sequence[j]] * 20 + AADict[sequence[j+1]]] +1
        if sum(tmpCode) != 0:
            tmpCode = [i/sum(tmpCode) for i in tmpCode]
        code = code + tmpCode
        encodings.append(code)
    return encodings

There is another file (main) from where the arguments fastas come from which is basically a list of strings where every string is a protein sequence. I am finding it really difficult to understand the nested loops that were used:
    for i in fastas:
        name, sequence = i[0], re.sub('-', '', i[1])
        code = [name]
        tmpCode = [0] * 400
        for j in range(len(sequence) - 2 + 1):
            tmpCode[AADict[sequence[j]] * 20 + AADict[sequence[j+1]]] = tmpCode[AADict[sequence[j]] * 20 + AADict[sequence[j+1]]] +1
        if sum(tmpCode) != 0:
            tmpCode = [i/sum(tmpCode) for i in tmpCode]
        code = code + tmpCode
        encodings.append(code)

I have spent 4-5 hours on this but I am still finding it really difficult to follow. I would really appreciate if anyone can explain the steps involved in these loops. Thank you!
Edit: The github link to the files are :

DPC.py
iFeature.py

The github link to the python toolkit: iFeature

**Tags:** python, featurecounts
> **Comments:**
> **username_1**: One thing that may help when trying to understand other peoples code is to add print statements and possibly break statements at various parts of the code.  You can print out exactly what is happening in the loop; for example, in the nested loop print j, print the tmpCode index, print the value at the tmp code etc.  
> **username_0**: @user438383, deleted  

---

## 1 answers

### Answer by username_1 on 2021-09-11. Score: 3 | Accepted answer

A few additional hints that may help clarify the algorithm:

The `20` magic number is because there are twenty amino acids. The `400` magic number is because there are `20 * 20` potential dipeptides.

These peptides are then hashed by converting their letter to a number in the range [0, 20). You can then multiple one of them by 20 and add the other to get a number between [0, 400). In the case of this function the first amino acid "code" is multiplied by 20. This number can be converted back to the dipeptide sequence when outputting the data. The translation table they use is generated here `diPeptides = [aa1 + aa2 for aa1 in AA for aa2 in AA]`.

The nested loops are to loop through each entry and then each sequence to get every dipeptide sequence, which can be done in linear time.

Just as a quick note on hashing DNA and peptide sequences. You can generally convert them to an array index by using increasing powers of the alphabet size multiplied by the letter index of the alphabet. For example, for DNA you can convert `A=0, C=1, G=2, T=3`, and you can hash fourmers by using `4^4 * a[i] + 4^3 * a[i + 1] + 4^2 * a[i + 2] + 4^1 * a[i + 3]`. In code you may see this performed with bitshifts for DNA since the alphabet size is a power of 2.

The advantage of this hashing scheme is. thateach sequence is guaranteed to have a unique index. The problem with this method is that as if you wish to use longer k-mers the memory usage will grow exponentially. For example, for 16-mers you need 4 billion combinations, which is the size of a 32 bit unsigned integer.

> **Comments:**
> **username_0**: Thank you so much. I am trying to follow what your suggestion. I am getting all sorts of error messages. I have very little programming skills. I only learnt to work with python on jupyter notebook. This toolkit (or any toolkit, I presume). works across multiple files at a time I presume. I am completely lost.  
> **username_0**: I have understood the concept of hashing i.e. `AADict={'A': 0,  'C': 1,  'D': 2, 'E': 3, 'F': 4, 'G': 5, 'H': 6, 'I': 7, 'K': 8, 'L': 9, 'M': 10, 'N': 11, 'P': 12, 'Q': 13, 'R': 14, 'S': 15, 'T': 16, 'V': 17, 'W': 18, 'Y': 19}`  
> **username_0**: I understood multiplying one of them by 20 and add the other to get a number between [0, 400). But still these 2 line ```if sum(tmpCode) != 0:             tmpCode = [i/sum(tmpCode) for i in tmpCode]``` are really bothering me  
> **username_1**: They are checking if the sum is larger than zero.  Then they are normalizing the totals to sum to 1.0; ie. calculating the frequency of each dipeptide.  
> **username_0**: It's working now. Thank you so much. I really appreciate  

---

