У меня есть файл SAM с полем RX:, содержащим 12 баз, разделенных посередине -
, т.е. RX:Z:CTGTGC-TCGTAA
Я хочу удалить дефис из этого поля, но я не могу просто удалить все дефисы из всего файла, так как имена для чтения содержат их, например, 1713704_EP0004-T
В основном пытались tr,
, но это просто удаление всех дефисов из файла .:
tr -d '"-' < sample.fq.unaln.umi.sam > sample.fq.unaln.umi.re.sam
Input - это большой SAM-файл, содержащий более 10 000 000 строк, например:
1902336-103-016_C1D1_1E-T:34 99 chr1 131341 36 146M = 131376 182 GGACAGGGAGTGTTGACCCTGGGCGGCCCCCTGGAGCCACCTGCCCTGAAAGCCCAGGGCCCGCAACCCCACACACTTTGGGGCTGGTGGAACCTGGTAAAAGCTCACCTCCCACCATGGAGGAGGAGCCCTGGGCCCCTCAGGGG NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN MC:Z:147M MD:Z:83T62cD:i:4 cE:f:0 PG:Z:bwa RG:Z:A MI:Z:34 NM:i:1 cM:i:3 MQ:i:36 UQ:i:45 AS:i:141 XS:i:136 RX:Z:CTGTGC-TCGTAA
Желаемый результат (то есть последнее поле)
1902336-103-016_C1D1_1E-T:34 99 chr1 131341 36 146M = 131376 182 GGACAGGGAGTGTTGACCCTGGGCGGCCCCCTGGAGCCACCTGCCCTGAAAGCCCAGGGCCCGCAACCCCACACACTTTGGGGCTGGTGGAACCTGGTAAAAGCTCACCTCCCACCATGGAGGAGGAGCCCTGGGCCCCTCAGGGG NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN MC:Z:147M MD:Z:83T62cD:i:4 cE:f:0 PG:Z:bwa RG:Z:A MI:Z:34 NM:i:1 cM:i:3 MQ:i:36 UQ:i:45 AS:i:141 XS:i:136 RX:Z:CTGTGCTCGTAA
Как мне решить эту проблему?
3 ответа
Я решил эту проблему с помощью pysam, который работает быстрее, безопаснее и требует меньше места на диске, поскольку файл sam не требуется. Это не идеально, я все еще изучаю Python и использую pysam в течение половины дня.
import pysam
import sys
from re import sub
# Provide a bam file
if len(sys.argv) == 2:
assert sys.argv[1].endswith('.bam')
# Makes output filehandle
inbamfn = sys.argv[1]
outbamfn = sub('.bam$', '.fixRX.bam', inbamfn)
inbam = pysam.Samfile(inbamfn, 'rb')
outbam = pysam.Samfile(outbamfn, 'wb', template=inbam)
# Counters for reads processed and written
n = 0
w = 0
# .get_tag() retrieves RX tag from each read
for read in inbam.fetch(until_eof=True):
n += 1
umi = read.get_tag('RX')
assert umi is not None
umifix = umi[:6] + umi[7:]
read.set_tag('RX', umifix, value_type='Z')
if '-' in umifix:
print('Hyphen found in UMI:', umifix, read)
break
else:
w += 1
outbam.write(read)
inbam.close()
outbam.close()
print ('Processed', n, 'reads:\n',
w, 'UMIs written.\n',
str(int((w / n) * 100)) + '% of UMIs fixed')
Этот шаблон находится на многих записях, которые вы хотите редактировать, и всегда находится в конце строки? Если так -
sed -E 's/^(.*)(\s..:.:......)-(......\s*)$/\1\2\3/' < sample.fq.unaln.umi.sam > sample.fq.unaln.umi.re.sam
Лучшее решение - работать с файлами BAM, а не с файлами SAM, и использовать подходящую библиотеку BAM-анализатора / записи, такую как htslib.
Не имея этого, вы можете что-то объединить, выполнив поиск регулярного выражения ^RX:Z:
в необязательных тегах (столбцы 12 и выше).
Работать с колонками, хотя это возможно, сложно с sed. Вместо этого вот как это сделать в awk:
awk -F '[[:space:]]*' '{
for (i = 12; i <= NF; i++) {
if ($i ~ /^RX:Z:/) gsub("-", "", $i)
}
}
1' file.sam
И вот примерно такое же решение, как Perl "one-liner":
perl -ape '
for (@F[11..(scalar @F)]) {
s/-//g if /^RX:Z:/;
}
$_ = join("\t", @F);
' file.sam
Чтобы выполнить замену в исходном файле, вы можете передать параметр -i.bak
в perl
(это создаст резервную копию file.sam.bak
; если вы не хотите создавать резервную копию, опустите расширение) ,
Похожие вопросы
Новые вопросы
regex
Регулярные выражения предоставляют декларативный язык для сопоставления шаблонов в строках. Они обычно используются для проверки, синтаксического анализа и преобразования строк. Поскольку регулярные выражения не полностью стандартизированы, все вопросы с этим тегом должны также включать тег, определяющий применимый язык программирования или инструмент.