# Finding proteins in a sequence

I have a file with protein sequences, all on a single line, like this:

>Contig_1 1FFPMPQ*CCLFSSSYLPA*AIMVTGSCQTLVQDKV*CLASCHVMIPPCVFHPIYPLFTWSPLHPIISGCF*AVCMCSWIHALFVEIILSWSLSLPFTFEISSD>Contig_2 1FFPCHNSVVYFLLLICLLKPLWSQGVVRHWYRTRCDAWLAVML*YLHVSFIPSIHFLLGRLCTLLYLDVFELYACAAGFMPCLLR*FSLGHSLFLLPLKFPATVKFFSLLGQIMNNISLMNDLQTGEKLQETH*EVEDKSALLVSIIESRCCVTLQPQDFSN*HLGKL*KSVGQKLK*VNDQITY*


I want to print all sequences between an M residue and a * that are at least 6 residues long, and I would like the output like this:

>contig_1.1.1
M.......*
>contig_1.1.2
M........*
>contig_2.1.1
M............*
>contig_2.1.2
M......*


Where the first number after the underscore is the number found in as the first character of the sequence (it is the reading frame) and the second number is the sequence number. and the last number is the fragment number. So, since the 1st sequence starts with;

>Contig_1 1FFPMPQ


The name will be >Contig_1.1 and each fragment found will be >Contig_1.1.1, >Contig_1.1.2, ... , >Contig_1.1.N.

After implementing the suggestion in the answer below and escaping the * in my regular expression, my current code is:

import sys
import re

myprotein = ">Contig_1 1FFPMPQ*CCLFSSSYLPA*AIMVTGSCQTLVQDKV*CLASCHVMIPPCVFHPIYPLFTWSPLHPIISGCF*AVCMCSWIHALFVEIILSWSLSLPFTFEISSD>Contig_2 1FFPCHNSVVYFLLLICLLKPLWSQGVVRHWYRTRCDAWLAVML*YLHVSFIPSIHFLLGRLCTLLYLDVFELYACAAGFMPCLLR*FSLGHSLFLLPLKFPATVKFFSLLGQIMNNISLMNDLQTGEKLQETH*EVEDKSALLVSIIESRCCVTLQPQDFSN*HLGKL*KSVGQKLK*VNDQITY*"
# parse record
my_protein = []
for line in myprotein:
if not line.startswith('>'):
my_protein.append(line)
else:
header = line

# build sequence
my_pro = ''.join(my_protein)

# cleave sequence
peptides = re.findall(r'(M[A-Z]{6,}\*)', my_pro)

# build a formatted list
records = ["%sNo.%d\n%s\n" % (header, idx + 1, fragment) for idx, fragment in     enumerate(peptides)]

# print list
for record in records:
sys.stdout.write("%s" % (record))


And it prints:

 >No.1
MVTGSCQTLVQDKV*
>No.2
MIPPCVFHPIYPLFTWSPLHPIISGCF*
>No.3
MNNISLMNDLQTGEKLQETH*


How can I change this to get my desired output format?

• re.findall('M[A-Z]{6,}*', seq) May 1 '18 at 15:01
• My apologies. the back-slash in my code got stripped for some reason. Try re.findall('M[A-Z]{6,}\*', seq) May 1 '18 at 15:24
• Hi and welcome to the site! When posting this sort of question, please always include the errors you get. Telling us "this doesn't work" is really not very helpful, it is always better to explain how it fails. May 1 '18 at 15:47
• Sorry for posting like that I just update my question so it would be great if you could help. Thanks May 1 '18 at 16:30

## 1 Answer

The * character has a special meaning in regular expressions, it means "0 or more". So when you write {6,}*, the regex engine tries to apply the "0 or more" to the {6,*} and gets confused:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.6/re.py", line 222, in findall
return _compile(pattern, flags).findall(string)
File "/usr/lib/python3.6/re.py", line 301, in _compile
p = sre_compile.compile(pattern, flags)
File "/usr/lib/python3.6/sre_compile.py", line 562, in compile
p = sre_parse.parse(p, flags)
File "/usr/lib/python3.6/sre_parse.py", line 855, in parse
p = _parse_sub(source, pattern, flags & SRE_FLAG_VERBOSE, 0)
File "/usr/lib/python3.6/sre_parse.py", line 416, in _parse_sub
not nested and not items))
File "/usr/lib/python3.6/sre_parse.py", line 619, in _parse
source.tell() - here + len(this))
sre_constants.error: multiple repeat at position 10


In order to use special characters literally, as simple strings, you need to escape them by adding a \ before them. So try:

import re
myprotein = ">Contig_1 1FFPMPQ*CCLFSSSYLPA*AIMVTGSCQTLVQDKV*CLASCHVMIPPCVFHPIYPLFTWSPLHPIISGCF*AVCMCSWIHALFVEIILSWSLSLPFTFEISSD"
protein = re.findall('M[A-Z]{6,}\*',myprotein)
print(protein)
['MVTGSCQTLVQDKV*', 'MIPPCVFHPIYPLFTWSPLHPIISGCF*']


To get the output you asked for while reading from a file, you can do:

import sys
import re

proteinFile = sys.argv[1]

with open(proteinFile, 'r') as f:
for line in f:
## Split the long input line into the list 'sequences'
sequences = line.rstrip('\n').split('>')

for i, k in list(enumerate(sequences)):
## Skip the first element which will be empty.
## there must be a pythonic way of doing this, but I'm
## a Perl hacker, so I don't know it.
if len(k) == 0:
continue

seqName, seq = k.split(' ')
## Get the frame
frame = seq[0]
## Remove the frame from the sequence
seq = seq[1:]
# cleave sequence
peptides = re.findall(r'(M[A-Z]{6,}\*)', seq)

for idx, peptide in enumerate(peptides):
print(">%s.%s.%d\n%s" % (seqName, frame, idx+1, peptide) )