Есть ли способ python для сопоставления фрагментов в пределах диапазона

У меня есть несколько генов, которые были охвачены различными чтениями. Одна проблема заключается в том, что в некоторых случаях, когда один ген покрывается несколькими прочтениями. Я хочу поймать все фрагменты прочтений, которые соответствуют длине гена (диапазону) [столбец 6 (генестарт) и столбец 7 генстоп], и добавить конечное поле, указывающее имя гена вместе с алфавитом «а», и для последовательных таких находок я хочу имя гена с добавлением b к нему.

Вход:

contig  230  3888 read1  1 8397 Gene1
contig  3343 3885 read2  1 8397 Gene1
contig  6030 8257 read4  1 8397 Gene1
contig  6030 8257 read10 1 8397 Gene1
contig  6260 8257 read7  1 8397 Gene1
contig  6030 8257 read8  1 8397 Gene1
contig  6190 6345 read10 1 8397 Gene1
contig   0   3124 read27 26 406 Gene12
contig  100  200  read30 26 406 Gene12 

Желаемый результат:

contig  230  3888 read1  1 8397 Gene1 Gene1a
contig  3343 3885 read2  1 8397 Gene1 covered
contig  6030 8257 read4  1 8397 Gene1 Gene1b
contig  6030 8257 read10 1 8397 Gene1 covered
contig  6260 8257 read7  1 8397 Gene1 covered
contig  6030 8257 read8  1 8397 Gene1 covered
contig  6190 6345 read10 1 8397 Gene1 covered
contig   0   3124 read27 26 406 Gene12 Gene12a
contig  100  200  read30 26 406 Gene12 covered

Код:

with open(input_file, "r") as f_in, open(output_file, "w") as f_out:
    gene_dict = {}
    for line in f_in:
        fields = line.strip().split()
        gene_name = fields[6]
        read_start = int(fields[1])
        read_end = int(fields[2])
        gene_start = int(fields[4])
        gene_end = int(fields[5])
        if gene_name not in gene_dict:
            gene_dict[gene_name] = []
        gene_found = False
        for gene_frag in gene_dict[gene_name]:
            frag_start = gene_frag[0]
            frag_end = gene_frag[1]
            if read_start <= frag_start <= read_end or read_start <= frag_end <= read_end:
                gene_found = True
                break
        if gene_found:
            gene_dict[gene_name].append((gene_start, gene_end))
            gene_count = chr(ord('a') + len(gene_dict[gene_name]) - 1)
            fields.append(f"{gene_name}{gene_count}")
        else:
            gene_dict[gene_name] = [(gene_start, gene_end)]
            fields.append(f"{gene_name}")
        f_out.write("\t".join(fields) + "\n")

Я не получаю желаемого результата. Результат, который я получил

contig  230  3888 read1  1 8397 Gene1 Gene1
contig  3343 3885 read2  1 8397 Gene1 Gene1
contig  6030 8257 read4  1 8397 Gene1 Gene1
contig  6030 8257 read10 1 8397 Gene1 Gene1
contig  6260 8257 read7  1 8397 Gene1 Gene1
contig  6030 8257 read8  1 8397 Gene1 Gene1
contig  6190 6345 read10 1 8397 Gene1 Gene1
contig   0   3124 read27 26 406 Gene12 Gene12
contig  100  200  read30 26 406 Gene12 Gene12

Файл разделен табуляцией, хотя здесь я не создал вкладку примера. Пожалуйста, укажите, где я ошибаюсь.

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

tripleee 10.05.2023 15:59

Кроме того, кстати, chr(ord('a')) — это действительно безумный способ написать просто 'a' (-:

tripleee 10.05.2023 16:00

Я хочу проверить, попадает ли диапазон значений в столбце 2 и столбце 3 в диапазон в столбцах 5 и 6. В моем случае несколько случаев диапазона в столбце 2 и столбце 3 попадают, поэтому я хочу добавить ген naem+алфавит, чтобы указать каждое совпадение с диапазоном. Для последовательных совпадений внутри гена я хочу написать имя гена и увеличить алфавит.

nivitian 10.05.2023 16:06

Для Gene1, read_start <= frag_start <= read_end or read_start <= frag_end <= read_end никогда не будет правдой. Пожалуйста, перепроверьте условия. Кроме того, Gene1a никогда не будет выводиться. Возможно вам нужен fields.append(f"{gene_name}a") за ген не найден. И, очевидно, ваш код не содержит никаких утверждений о covered.

ken 10.05.2023 16:50
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
4
79
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Я пытался прокомментировать шаги, но спрашивайте, если не ясно. Я использовал логику range() и set(), чтобы найти совпадения.

data='''contig  230  3888 read1  1 8397 Gene1
contig  3343 3885 read2  1 8397 Gene1
contig  6030 8257 read4  1 8397 Gene1
contig  6030 8257 read10 1 8397 Gene1
contig  6260 8257 read7  1 8397 Gene1
contig  6030 8257 read8  1 8397 Gene1
contig  6190 6345 read10 1 8397 Gene1
contig   0   3124 read27 26 406 Gene12
contig  100  200  read30 26 406 Gene12 '''

#initialise variables
last_gene=''
gene_span=range(0)
total_read_span=range(0)

for contig in data.split('\n'): #iterate over contigs
    fields=contig.split() #split lines into separate fields. Will need to be .split('\t) for tab-separated data
    read_span=range(int(fields[1]),int(fields[2])+1)
    if (gene := fields[6]) != last_gene: #check if new gene or previous gene
        last_gene=gene
        alphabet=iter('abcdefghijklmnopqrstuvqxyz') #set up an alphabet iterator to assign gene suffixes
        gene_span=range(int(fields[4]),int(fields[5])+1)
        total_read_span=range(0) #initialise total_read_span, i.e. the range of the sequence read
    if len(set(read_span)&set(gene_span)): #check if read or gene spans overlap (the length of a set of intersecting values > 0)
        if len(set(read_span)-set(total_read_span)): #check if the contig read has values outside of current total read span
            print(f'{contig} {gene}{next(alphabet)}')
            total_read_span=range(min(total_read_span.start,read_span.start),max(total_read_span.stop,read_span.stop)) #update total read span
        else:
            print(f'{contig} covered')
    else:
        print(f'{fields[3]} has no overlap with {gene}')

Спасибо получилось хорошо!! Итерация алфавитов была действительно хорошей.

nivitian 10.05.2023 21:29

хороший, что касается алфавита, в string библиотеке Python есть ascii_lowercase какая именно эта строка :) docs.python.org/3/library/string.html#string.ascii_lowercase

Adam.Er8 11.05.2023 09:33

Это так, но реализация этого занимает примерно столько времени, сколько нужно напечатать, а потом я тоже должен это запомнить!

bc1155 11.05.2023 10:02

Другие вопросы по теме