grep каждую четвертую строку в .fastq - PullRequest
0 голосов
/ 24 ноября 2018

Я работаю на машине с Linux, используя Bash.

Мой вопрос, как я могу пропустить строки в файле запроса, используя grep?

Я работаю с большим файлом ~ 16 Гб .fastq с именем example.fastq, который имеет следующий формат.

example.fastq

@SRR6750041.1 1/1
CTGGANAAGTGAAATAATATAAATTTTTCCACTATTGAATAAAAGCAACTTAAATTTTCTAAGTCG
+
AAAAA#EEEEEEEEEEEEEEEEEEEEEEEAEEEEEEEEEEEEEEEEEEEEEEEEEA<AAEEEEE<6
@SRR6750041.2 2/1
CTATANTATTCTATATTTATTCTAGATAAAAGCATTCTATATTTAGCATATGTCTAGCAAAAAAAA
+
AAAAA#EE6EEEEEEEEEEEEAAEEAEEEEEEEEEEEE/EAE/EAE/EA/EAEAAAE//EEAEAA6
@SRR6750041.3 3/1
ATCCANAATGATGTGTTGCTCTGGAGGTACAGAGATAACGTCAGCTGGAATAGTTTCCCCTCACAG
+
AAAAA#EE6E6EEEEEE6EEEEAEEEEEEEEEEE//EAEEEEEAAEAEEEAE/EAEEA6/EEA<E/
@SRR6750041.4 4/1
ACACCNAATGCTCTGGCCTCTCAAGCACGTGGATTATGCCAGAGAGGCCAGAGCATTCTTCGTACA
+
/AAAA#EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEAE/E/<//AEA/EA//E//
@SRR6750041.5 5/1
CAGCANTTCTCGCTCACCAACTCCAAAGCAAAAGAAGAAGAAAAAGAAGAAAGATAGAGTACGCAG
+
AAAAA#EEEEEEEEEEEEEAEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/EEEAEEEAEEE<EE/E

Мне нужно извлечь строкисодержит интересующие строки @SRR6750041.2 @SRR6750041.5, хранящиеся в массиве bash с именем IDarray, а также 3 строки после каждого совпадения.Следующая команда grep позволяет мне сделать это

for ID in "${IDarray[@]}";
    do
    grep -F -A 3 "$ID " example.fastq 
    done

Это правильно выдает следующее:

@SRR6750041.2 2/1
CTATANTATTCTATATTTATTCTAGATAAAAGCATTCTATATTTAGCATATGTCTAGCAAAAAAAA
+
AAAAA#EE6EEEEEEEEEEEEAAEEAEEEEEEEEEEEE/EAE/EAE/EA/EAEAAAE//EEAEAA6
@SRR6750041.5 5/1
CAGCANTTCTCGCTCACCAACTCCAAAGCAAAAGAAGAAGAAAAAGAAGAAAGATAGAGTACGCAG
+
AAAAA#EEEEEEEEEEEEEAEEEEEEEEEEEEEEEEEEEEEEEEEEEEE/EEEAEEEAEEE<EE/E

Я ищу способы ускорить этот процесс ... одним из способов было быуменьшить количество строк, ищущих с помощью grep, ограничивая поиск строками, начинающимися с @, или пропуская строки, которые не могут содержать совпадения @SRR6750041.1, такие как строки 2,3,4 и 6,7,8 и т. д. Есть лиспособ сделать это с помощью grep?Альтернативные методы также приветствуются!

1 Ответ

0 голосов
/ 27 ноября 2018

Вот несколько мыслей с примерами.Для целей тестирования я создал тестовый набор, поскольку мини-версия Yours example_mini.fastq имеет размер 145 МБ, а IDarray имеет 999 элементов (интересов).

Ваша версия имеет такую ​​производительность (более 2 минут в пространстве пользователя):

$ time for i in "${arr[@]}"; do grep -A 3 "${i}" example_mini.fastq; done 1> out.txt
real    3m16.310s
user    2m9.645s
sys     0m53.092s

$ md5sum out.txt
8f199a78465f561fff3cbe98ab792262  out.txt

Первое обновление grep до конца grep после первого совпадения -m 1. Я предполагаю, что идентификатор интереса уникален.Это сужает на 50% сложности и занимает около 1 минуты в пользовательском пространстве:

$ time for i in "${arr[@]}"; do grep -m 1 -A 3 "${i}" example_mini.fastq; done 1> out.txt
real    1m19.325s
user    0m55.844s
sys     0m21.260s

$ md5sum out.txt
8f199a78465f561fff3cbe98ab792262  out.txt

Эти решения линейно зависят от количества элементов.Вызвать n раз grep для огромного файла.

Теперь давайте внедрим в AWK только для одного запуска, я экспортирую IDarray во входной файл, чтобы я мог обработать за один запуск.Я загружаю большой файл в ассоциативный массив для каждого идентификатора, а затем зацикливаю 1x массив идентификаторов для поиска.Это общий сценарий, в котором Вы можете определить регулярное выражение и количество строк после печати.Это имеет сложность только с одним прогоном сравнения файлов + N.Это на 2000% больше ускорения:

$ for i in "${arr[@]}"; do echo $i; done > IDarray.txt
$ time awk '
(FNR==NR) && (linesafter-- > 0) { arr[interest]=arr[interest] RS $0; next; }
(FNR==NR) && /^@/ { interest=$1; arr[interest]=$0; linesafter=3; next; }
(FNR!=NR) && arr[$1] { print(arr[$1]); }
' example_mini.fastq IDarray.txt 1> out.txt
real    0m7.044s
user    0m6.628s
sys     0m0.307s

$ md5sum out.txt
8f199a78465f561fff3cbe98ab792262  out.txt

Как в заголовке, если вы действительно можете подтвердить, что каждая четвертая строка является идентификатором интереса, и три строки после нее будут напечатаны.Вы можете упростить это и ускорить еще на 20%:

$ for i in "${arr[@]}"; do echo $i; done > IDarray.txt
$ time awk '
(FNR==NR) && (FNR%4==1) { interest=$1; arr[interest]=$0; next; }
(FNR==NR) { arr[interest]=arr[interest] RS $0; next; }
(FNR!=NR) && arr[$1] { print(arr[$1]); }
' example_mini.fastq IDarray.txt 1> out.txt
real    0m5.944s
user    0m5.593s
sys     0m0.242s

$ md5sum out.txt
8f199a78465f561fff3cbe98ab792262  out.txt

Для файла объемом 1,5 ГБ с 999 элементами время поиска составляет:

real    1m4.333s
user    0m59.491s
sys     0m3.460s

Так, согласно моим прогнозам на моей машинеВаш 15-гигабайтный пример с 10-килобайтными элементами займет около 16 минут в пользовательском пространстве.

...