匹配文件中的部分行(python)

时间:2012-04-21 20:42:36

标签: python regex bioinformatics fasta complement

我目前在文件中有一个基因列表。每条线都有一条染色体及其信息。这样的条目显示为:

NM_198212 chr7 + 115926679 115935830 115927071 11593344 2 115926679 ,'115933260', 115927221 ,'115935830' ,

染色体的序列从 115926679 开始,并持续到(但不包括)碱 115935830

如果我们想要拼接序列,我们使用外显子。第一个延伸自 115926679 155927221 ,第二个从'115933260'到'115935830'

但是,在使用互补序列时遇到问题,例如:

NM_001005286 chr1 - 245941755 245942680 245941755 245942680 1 245941755 ,'245942680'

由于第3列是' - ',这些坐标是指反义链(链的互补链)。第一个碱基(粗体)匹配有义链上的最后一个碱基(斜体)。由于文件只有感测架,我需要尝试将反义链上的坐标转换为有义链,选择正确的序列然后反向补充它。

那就是说,我只编程了大约半年,并且不确定如何开始这样做。

我写了一个正则表达式:

'(NM_\d+)\s+(chr\d+)([(\+)|(-)])\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+),(\d+),s+(\d+),(\d+),'

但我现在不确定如何启动此功能...... 如果有人能帮助我开始这一点,或许让我看到如何做到这一点,我会非常感激。

好的:假设这是25号染色体:

AAAAAAAAAACCCCCCCCCCTTTTTTTTTTGGGGGGGGGG

(每个角色有10个)。

现在:如果我正在寻找一个未拼写的基因:chr25 + 10 20

然后基因从第10位开始(从0开始),然后上升到但不包括位置20.所以它:

CCCCCCCCCC

这很容易。它很好地匹配python字符串切片。

如果我给你的话会更加困惑:

chr25 - 10 20

你拥有的是正向链。但这个基因位于负(互补)链上。记住染色体看起来像一条双链:

AAAAAAAAAACCCCCCCCCCTTTTTTTTTTGGGGGGGGGG
TTTTTTTTTTGGGGGGGGGGAAAAAAAAAACCCCCCCCCC

我们正在寻找底链上的基因。意思是我们从右边开始从0开始计算。从左边开始编号,从右边开始编号。所以我想要的是AAAAAAAAAA。

抓住的是我只给你顶线。我没有给你底线。 (你可以从顶层产生自己 - 但考虑到它有多大,我建议反对。)

所以你需要转换坐标。在底链上,碱基0(最右边的C)与顶部链上的碱基39相对。基数1与基数38相对。基数2与情况37相反。(重点:注意每次添加这两个数字时会发生什么情况。)因此,基数10与基数29相对,基数19与基数20相对。 / p>

所以:如果我想在底线上找到10-20的基数,我可以看一下顶部的20-29(然后反向补充它)。

我需要弄清楚如何将底线上的坐标转换为底线上的等效坐标。是的:这非常令人困惑

我试过weronika's original answer

fields = line.split(' \t')
geneID, chr, strand = fields[:2]
start = int(fields[3])
end = int(fields[4])
if strand == '-':
    start,end = -(start + 1), -(end + 1) # this part was changed from original answer.

这是正确的轨道,但这还不够。这将取10和20,并将其变为20和10。

我知道我可以通过这样做来反转字符串补充:

r = s[::-1]
bc = {'A': 'T', 'C': 'G', 'G': 'C', 'T': 'A'}
l = list(r)
o = [bc[base] for base in l]
     return ''.join(o)

编辑!这看起来是否正确?!

fp2 = open('chr22.fa', 'r')
fp = open('chr22.fa', 'r')
for line in fp2:
    newstring = ''
    z = line.strip()
    newstring += z
for line in fp:
    fields = line.split('\t')
    gene_ID, chr, strand = fields[:2]
    start = int(fields[3])
    end = int(fields[4])
    bc = {'A': 'T', 'C': 'G', 'G': 'C', 'T': 'A', 'a': 't', 't': 'a', 'c':'g', 'g':'c', 'N':'N', 'n':'n'}
    l = list(newstring)        
    if strand == '+':
        geneseq = ''.join([bc[base] for base in l[start:end]]) 
    if strand == '-':
        newstart, newend = -(start + 1), -(end + 1)
        genseq = ''.join([bc[base] for base in l[newstart:newend]]) 

4 个答案:

答案 0 :(得分:0)

我没有理解域名问题,但看起来你正试图过多地填充一个正则表达式。尝试将其分解为更简单的子问题,如下所示(在伪代码中):

if third column is a '+'
    parseRegularSequence()
else
    parseComplementarySequence()

答案 1 :(得分:0)

正如我对这个问题的评论所指出的,这似乎是一种非常奇怪的文件格式,因此我最初的困惑。

注意:如果这是标准的生物学文件格式之一,那么最好使用Biopython或类似的解析它。

如果你想进行自己的解析,正则表达式似乎仍然是错误的方法 - 使用简单的空格/制表符分隔文件难以阅读和不必要。 我假设您已经解析了您的染色体fasta文件并将所有染色体的序列作为chrom_sequences名称:seq字典,并且您还具有reverse_complement函数(这些都很容易手动实现,但可能更好地完成biopython)。

fields = line.split(' ')  # or '\t' instead of ' ' if the file is tab-separated
gene_ID, chr, strand = fields[:2]
start, end = [int(x) for x in fields[3:5])
this_chromosome_seq = chrom_sequences[chr]
# if strand is +, just take the sequence based on the start-end position
if strand == '+':
  # be careful about off-by-one errors here - some formats give you a 1-based position, 
  #  other formats make it 0-based, and they can also be end-inclusive or end-exclusive
  gene_sequence = this_chromosome_seq[start:end]
# if your coordinates really are given as antisense strand coordinates when strand is -,
#  you just need to subtract them from the chromosome length to get sense-strand coordinates,
#  (switching start and end so they're still in smaller-to-larger order),
#  and then reverse-complement the resulting sequence. 
if strand == '-':
  chrom_length = len(this_chromosome_seq)
  # again, be careful about off-by-one errors here!
  new_start,new_end = chrom_length-end, chrom_length-start
  gene_sequence = reverse_complement(this_chromosome_seq[new_start:new_end])

原始回答,实际上并未按要求进行操作:

如果您只想获得开始/结束位置,请执行以下操作:

fields = line.split(' ')  # or '\t' instead of ' ' if the file is tab-separated
gene_ID, chr, strand = fields[:2]
start = int(fields[3])
end = int(fields[4])
if strand == '-':
  start,end = end,start

然后你必须解析你的fasta文件以实际获取这些起始端坐标的序列,并在strand=='-'时反向补充它。同样,我认为Biopython可以为您完成大部分工作。

另一个注意事项 - Biostar是一个专门针对生物信息学的优秀StackExchange类型网站,您可能会在那里获得更好的答案。

答案 2 :(得分:0)

如果您使用否定编号对字符串进行切片,则Python会从末尾向后计数。

complement = {'A': 'T', 'C': 'G', 'G': 'C', 'T': 'A'}
s = "AAAAAAAAAACCCCCCCCCCTTTTTTTTTTGGGGGGGGGG"
"".join(complement[c] for c in s[-20:-10])

编辑:

你的编辑看起来对我来说是对的,是的。我非常擅长检查fencepost errors,但你最好还是去看看那些比我还要好的事情!

我已经将你的代码重写为Pythonic,但没有改变任何重大内容。

bc = {'A': 'T', 'C': 'G', 'G': 'C', 'T': 'A', 'N':'N'}

f = open('chr22.fa')
l = ''.join(line.strip() for line in f)
f.seek(0)

for line in f:
    fields = line.split('\t')
    gene_ID, chr, strand = fields[:2]

    start = int(fields[3])
    end = int(fields[4])

    if strand == '-':
        start, end = -(start + 1), -(end + 1)

    geneseq = ''.join(bc[base.upper()] for base in l[start:end])

答案 3 :(得分:0)

我想(特别是因为你的文件很大),直接从文件缓冲区读取和写入会更容易。

假设您已经解析了头文件。您解析的行如下所示:

line = "NM_001005286 chr1 - 245941755 245942680 245941755 245942680 1"

然后确定起始/终止位置是什么(在反义坐标中):

name, chromosome, direction, start, end = line[:5]

然后,执行以下操作:

#Open up the file `chr1.txt`.
f = open("chr1.txt", "r")

#Determine the read length.
read_len = end - start

#Seek to the appropriate position (notice the second argument, 2 -- this means
#seek from the end of the file)
f.seek(-end, 2)

#Read the data
sense_seq = f.read(read_len)

之后,这只是将序列转换为反义的问题。

简单:)