
Я работаю над студенческим исследовательским проектом, который в значительной степени посвящен биоинформатике, и я иду по конвейеру обработки файлов. Немного предыстории: я работаю с метагеномными данными дробовика, которые представляют собой очень большие выборки A, T, G, C (нуклеотиды в образце ДНК), и, насколько я понял, некоторые квалификаторы. Я уже прошел несколько шагов конвейера, которые обрезали и очистили некоторые файлы, а также добавили некоторые квалификаторы. Важно то, что эти чтения в основном являются парными конечными чтениями, то есть два файла, считывающие нуклеотиды справа налево и слева направо.
До этого я забивал себе голову в основном только биологией и экологией, поэтому у меня нет никакого контекста для программирования или того, как/зачем что-то делать, или общих практик/функций и т. д. Вы поняли.
Тем не менее, я сам научился основам циклов for и манипуляции строками в UNIX, создав несколько файлов bash, которые проходили через разные папки, используя разные модули и функции. Вот пример кода:
cd ~/ncbi/public/sra/indian
for forward_read_file in *_1.fastq
do
rev=_2
reverse_read_file=${forward_read_file/_1/$rev}
perl /home/gomeza/shared/sharm646-2021-02-24-09_22/Softwares/NGSQCToolkit_v2.3.3/Trimming/AmbiguityFiltering.pl -i ${forward_read_file} -irev ${reverse_read_file} -c 1 -t5 -t3
rm ${forward_read_file} ${reverse_read_file}
done
#CAMEROON
cd ~/ncbi/public/sra/cameroon
for forward_read_file in *_1.fastq
do
rev=_2
reverse_read_file=${forward_read_file/_1/$rev}
perl /home/gomeza/shared/sharm646-2021-02-24-09_22/Softwares/NGSQCToolkit_v2.3.3/Trimming/AmbiguityFiltering.pl -i ${forward_read_file} -irev ${reverse_read_file} -c 1 -t5 -t3
rm ${forward_read_file} ${reverse_read_file}
done
и так далее для многих папок. Я использовал манипуляцию строками, чтобы заставить каждую итерацию цикла for вызывать парные конечные файлы, а затем некоторые аргументы и параметры для используемого мной модуля.
Большая проблема, с которой я сейчас столкнулся, заключается в том, что я не могу придумать способ спарить конечные файлы для следующего шага в конвейере, поскольку они содержат четыре случайных символа прямо перед расширением, и я не могу их предсказать. Они не содержат значимых данных, поэтому мой план — удалить их из имен файлов и продолжить так, как я делал.
Вот примеры проблемных файлов; проблема в четырех символах в конце строки. Если я избавлюсь от них, я смогу выполнять манипуляции со строками как обычно.
SRR5898908_1_prinseq_good_ZsSX.fastq SRR5898928_2_prinseq_good_VygO.fastq SRR5898979_1_prinseq_good_CRzI.fastq SRR6166642_2_prinseq_good_nqVP.fastq SRR6166693_2_prinseq_good_y_OD.fastq
SRR5898908_2_prinseq_good_HPTU.fastq SRR5898929_1_prinseq_good_p2mS.fastq SRR5898979_2_prinseq_good_vYcE.fastq SRR6166643_1_prinseq_good_fc8y.fastq SRR6166694_1_prinseq_good_Ka1C.fastq
SRR5898909_1_prinseq_good_X41r.fastq SRR5898929_2_prinseq_good_uO8g.fastq SRR5898980_1_prinseq_good_WuPS.fastq SRR6166643_2_prinseq_good_QUUK.fastq SRR6166694_2_prinseq_good_ZlNk.fastq
SRR5898909_2_prinseq_good_GbmA.fastq SRR5898930_1_prinseq_good_3qyA.fastq
Где начало SRRxxxxx — это образец, а1или2являются прямым и обратным чтением соответственно, отсюда и мои манипуляции со строками. Проблема в четырех символах в конце строки. Если я избавлюсь от них, я смогу выполнять манипуляции со строками как обычно. Мой наставник рекомендовал мне как-то использовать функции FIND или CUT и говорил об использовании возврата find в качестве переменной для манипуляций, но я чувствую, что это все равно приведет к той же проблеме.
Как можно безопасно удалить эти символы с помощью цикла for? Или как вы считаете, это будет работать лучше всего.
Спасибо!
решение1
Попробуйте что-то вроде этого:
for forward_read_file in *_1*.fastq; do
srr=$(echo "$forward_read_file" | cut -d_ -f1)
rrf_array=( $(find . -name "${srr}_2_*.fastq") )
case "${#rrf_array[@]}" in
0) echo "Warning: No reverse read file found for $forward_read_file" > /dev/stderr ;;
1) reverse_read_file="${rrf_array[1]}"
perl /home/gomeza/shared/sharm646-2021-02-24-09_22/Softwares/NGSQCToolkit_v2.3.3/Trimming/AmbiguityFiltering.pl -i "$forward_read_file" -irev "$reverse_read_file" -c 1 -t5 -t3
;;
*) echo "Error: multiple reverse read files found for $forward_read_file" > /dev/stderr ;;
esac
done
Это перебирает все _1
файлы. Он использует cut
для извлечения идентификатора образца SRR, а затем использует его с find
командой для поиска любых соответствующих _2
файлов. find
Вывод сохраняется в массиве, поскольку мы не знаем, сколько результатов может быть возвращено.
Он обрабатывает три возможных результата: ни одного совпадения (плохо), ровно 1 совпадение (хорошо, это то, что нам нужно) и более 1 совпадения (опять же, плохо).
Если результат только один, извлеките соответствующий файл из массива и обработайте его с помощью вашего скрипта Perl.
Если есть ноль или более одного результата, вывести предупреждающее сообщение в stderr и продолжить к следующему _1
имени файла. Вы можете добавить ; exit 1
(или другой код для обработки ошибки) перед ;;
для этих случаев, если хотите.
При этом игнорируются все части имен файлов, за исключением идентификатора образца SRR в начале и символа _1
или _2
, который идентифицирует его как файл прямого или обратного сопряжения.
Кстати, это можно было бы сделать с помощью оператора if; then; else
вместо оператора case
, но я подумал, что было бы полезно обрабатывать случаи «ноль» и «более одного». Например:
if [ "${#rrf_array[@]}" == 1 ];
reverse_read_file="${rrf_array[1]}"
perl /home/gomeza/shared/sharm646-2021-02-24-09_22/Softwares/NGSQCToolkit_v2.3.3/Trimming/AmbiguityFiltering.pl -i "$forward_read_file" -irev "$reverse_read_file" -c 1 -t5 -t3
else
echo "Warning: unknown problem with reverse read file for $forward_read_file" > /dev/stderr
fi
Если вы просто хотите игнорировать «проблемные» файлы, удалите блок else
.
Кстати, чтобы сделать ваш сценарий более читабельным, я предлагаю сделать что-то вроде этого в верхней части сценария:
AFilter='/home/gomeza/shared/sharm646-2021-02-24-09_22/Softwares/NGSQCToolkit_v2.3.3/Trimming/AmbiguityFiltering.pl'
и позже:
perl "$AFilter" -i "$forward_read_file" -irev "$reverse_read_file" -c 1 -t5 -t3
В качестве альтернативы, если скрипт(ы) perl являются исполняемыми (т. е. имеют #!/usr/bin/perl
или аналогичную строку shebang и установлен флаг исполняемости с помощью chmod +x
), вы можете просто добавить /home/gomeza/shared/sharm646-2021-02-24-09_22/Softwares/NGSQCToolkit_v2.3.3/Trimming/
в свой $PATH:
PATH="$PATH:/home/gomeza/shared/sharm646-2021-02-24-09_22/Softwares/NGSQCToolkit_v2.3.3/Trimming"
и запустите скрипт как:
AmbiguityFiltering.pl -i "$forward_read_file" -irev "$reverse_read_file" -c 1 -t5 -t3
решение2
Вы имеете в виду переименование названия?
Так:
cat a2 | sed -e 's|\(.*\)\(good_\)\(.*\)\(.fastq\)|mv \1\2\3\4 \1\2\4|'
mv SRR5898908_1_prinseq_good_ZsSX.fastq SRR5898908_1_prinseq_good_.fastq
mv SRR5898928_2_prinseq_good_VygO.fastq SRR5898928_2_prinseq_good_.fastq