Как использовать Python REGEX для улучшения указанных c терминов в шаблоне - PullRequest
3 голосов
/ 06 марта 2020

мой шаблон

Forward primer
CGAAGCCTGGGGTGCCCGCGATTT Plus 24 1 24 71.81 66.67 4.00 2.00 

Reverse primer
AAATCGGTCCCATCACCTTCTTAT Minus 24 420 397 59.83 41.67 5.00 2.00 

Product length
420 


Products on potentially unintended templates


>CP049108.1 Mycobacterium tuberculosis strain 5005 chromosome, complete genome product length = 495
Forward primer  1        CGAAGCCTGGGGTGCCCGCGATTT  24
Template        1930054  ........................  1930077

Reverse primer  1        AAATCGGTCCCATCACCTTCTTAT  24
Template        1930548  ........................  1930525


product length = 2946
Forward primer  1        CGAAGCCTGGGGTGCCCGCGATTT  24
Template        1927603  .......C....C..T..T...G.  1927626

Reverse primer  1        AAATCGGTCCCATCACCTTCTTAT  24
Template        1930548  ........................  1930525


>CP046728.2 Mycobacterium tuberculosis strain TCDC11 chromosome, complete genome product length = 420
Forward primer  1        CGAAGCCTGGGGTGCCCGCGATTT  24
Template        2150761  ........................  2150784

Reverse primer  1        AAATCGGTCCCATCACCTTCTTAT  24
Template        2151180  ........................  2151157


product length = 2595
Forward primer  1        CGAAGCCTGGGGTGCCCGCGATTT  24
Template        2148586  .......C....C..T..T...G.  2148609

Reverse primer  1        AAATCGGTCCCATCACCTTCTTAT  24
Template        2151180  ........................  2151157


>CP047258.1 Mycobacterium tuberculosis strain TCDC3 chromosome product length = 345
Forward primer  1        CGAAGCCTGGGGTGCCCGCGATTT  24
Template        2166300  ........................  2166323

Reverse primer  1        AAATCGGTCCCATCACCTTCTTAT  24
Template        2166644  ........................  2166621

Мне нужно

>CP049108.1 = 495   1930054 1930548 
>CP046728.2 = 420   2150761 2151180
>CP047258.1 = 345   2166300 2166644

Я микробиолог и Python новичок. Я попытался

import re
file = open(r"C:\\Users\\Lab\\Desktop\\amplicons\\ETRA", "r")
handle = file.read()
file.close()

pattern1 = re.compile(r'>.{5,10}\.\d')
matches1 = pattern1.finditer(handle)

for match1 in matches1:
    print(match1.group(0))

, но мне нужно указать c термины, следующие за моим номером доступа (например, номер доступа> CP049108.1). Я адаптирую ваши знания и к моей другой работе.

благодарю вас за помощь и заранее благодарю

Ответы [ 5 ]

3 голосов
/ 06 марта 2020

Вот то, что я придумал - >([\w\d]*?\.\d*?) .+= (\d+)\n.+\n.*?(\d+).+\n{2}.+\n.*?(\d+)

Давайте рассмотрим пример только с одним набором данных, вы можете вставить все данные, которые вы вставили, и по-прежнему получать результаты, пока у вас есть global установлен флаг True (по умолчанию python установлен *1007*)

> CP049108.1 Хромосома штамма Mycobacterium tuberculosis 5005, полная длина продукта генома = 495 Прямой праймер 1
CGAAGCCTGGGGTGCCCGCGATTT 24 Шаблон 1930054 ........................ 1930077

Обратный праймер 1 AAATCGGTCCCATCACCTTCTTAT 24 Шаблон
1930548 .. ...................... 1930525

Первая группа будет - CP049108.1

Вторая группа будет - 495

Третья группа будет - 1930054

Четвертая (и последняя) группа будет - 1930548

Конечно, теперь вы можно реструктурировать все данные так, как вы хотите. Если вы читаете данные из текстового файла, вы можете использовать этот фрагмент кода -

import re

with open('test.txt', 'r') as file:
    content = file.read()

pattern = re.compile(r'>([\w\d]*?\.\d*?) .+= (\d+)\n.+\n.*?(\d+).+\n{2}.+\n.*?(\d+)')

for match in pattern.finditer(content):
    output = '>{} = {} {} {}'.format(match.group(1), match.group(2), match.group(3), match.group(4))
    print(output)

Если я введу именно данные набор, который вы предоставили test.txt, я получаю этот вывод -

>CP049108.1 = 495   1930054 1930548
>CP046728.2 = 420   2150761 2151180
>CP047258.1 = 345   2166300 2166644

Regex Объяснение

>(\w+\.\d+) .+= (\d+)\n.+\n.*?(\d+).+\n{2}.+\n.*?(\d+)

  • Давайте проанализируем первый первая строка - >(\w+\.\d+) .+= (\d+)\n

    Сначала это соответствует CP049108, останавливается до тех пор, пока не будет найдена . (точка), а затем соответствует следующим цифрам, в данном случае - 1, останавливается до = достигнуто. Затем он объединит их, чтобы получить CP049108.1 в одной группе захвата

    Позже он будет захватывать цифры сразу после = и go до следующей строки, в данном случае это 495

  • Время для второй строки - .+\n

    Да, вторая строка просто игнорируется

  • Теперь третья строка - .*?(\d+).+\n{2}

    Он игнорирует все до тех пор, пока не достигнет первого набора цифр, захватывает их и переходит к следующей следующей строке (2 новые строки). В этом случае результат будет 1930054

  • Теперь четвертая строка - .+\n

    Это также игнорируется

  • Наконец, последняя строка - .*?(\d+)

    Это работает точно так же, как 3-я строка, результат - 1930548

Проверьте демо !

2 голосов
/ 06 марта 2020

Вы можете сопоставить следующее регулярное выражение, а затем извлечь содержимое трех групп захвата:

r'^(>CP\d{6}\.\d).+?\bproduct +length += +(\d+).*?^Template +(\d+).*?^Template +(\d+)'gms

Демо

Это можно сделать самодокументированием, используя Флаг Python VERBOSE (он же X).

Он получен из Perl свободного пробела , который я использовать, потому что я не знаком с Python. Читатель, который не знает Perl, сможет отлично это понять.

/
^                        # match beginning of line        
(>CP\d{6}\.\d)           # match '>CP', 6 digits, '.', 1 digit in cap group 1  
.+?                      # match 0+ characters, lazily (`?`)
\b                       # match a word break               
product\ +length\ +=\ +  # match 'product', 1+ spaces, 'length', 1+ spaces,
                         #   '=', 1+ spaces 
(\d+)                    # match 1+ digits in cap group 2
.*?                      # match 0+ characters, lazily (`?`)
^Template\ +             # match beginning of line, 'Template', 1+ spaces 
(\d+)                    # match 1+ digits in cap group 3
.*?                      # match 0+ characters, lazily (`?`)
^Template\ +             # match beginning of line, 'Template', 1+ spaces 
(\d+)                    # match 1+ digits in cap group 4                
/xgms                    # free-spacing, global, multiline, single-line modes

Значения различных режимов приведены по ссылке. В режиме свободного пробела неэкранированные пробелы вне классов символов удаляются перед анализом регулярного выражения. Поэтому пробелы, являющиеся частью выражения, например, между «product» и «length», должны быть защищены. Я решил избежать их здесь, но другие варианты заключаются в том, чтобы поместить каждый пробел в символьный класс ([ ]), использовать выражения Unicode \p{Space} или [[:space:\\ или, если необходимо, \s (символ пробела).

0 голосов
/ 06 марта 2020

Это то, что вам нужно:

matches=re.findall(r'(>.{5,10}\.\d).*?( = \d+).*?Template.*?( \d+).+?( \d+)', handle, re.DOTALL)
["".join(x) for x in matches]

Как видите, четыре группы объявлены с использованием круглых скобок в регулярном выражении. Каждая группа получит четыре части вашего вывода, разделенные пробелом. Вы присоединитесь к этому результату, чтобы получить желаемый результат.

0 голосов
/ 06 марта 2020

Я бы предложил подумать о логике c, которая вам нужна, а затем написать правила, чтобы помочь.

Вот полезная книга, которую я использовал для изучения регулярных выражений. Он охватывает основные правила c, которые можно использовать для получения необходимых результатов: http://diveinto.org/python3/regular-expressions.html

0 голосов
/ 06 марта 2020

Вот один из способов сделать это. Поиск в регулярных выражениях скорее зависит от того, соответствует ли текст предоставленному вами файлу.

rows = re.findall('(>.{5,10}).*length( = \d*).*\s*.*\s*Template\s*(   \d*).*\s*.*\s*Template\s*( \d*)', handle)
print('\n'.join(''.join(x) for x in rows))
...