Избегайте повторной загрузки файла в функцию - PullRequest
0 голосов
/ 04 сентября 2018

Я пытаюсь написать файл с функциями для получения файла fastta и (i) дать обзор файла, (ii) нарисовать гистограмму для распределения длин последовательностей. Я успешно написал следующий код, который работает:

from Bio import SeqIO
from prettytable import PrettyTable
import pylab
import numpy as np
import sys
%matplotlib inline

def fasta_outlook(fasta_file):
    '''Summarize the fasta file with #ofseq, length(min,max). Takes filename as string'''
   => sizes = [len(rec) for rec in SeqIO.parse(fasta_file,"fasta")]
    table = PrettyTable(['Parameter', 'Stats'])
    table.add_row(['No. of Sequences', len(sizes)])
    table.add_row(['Shortest seq.length', min(sizes)])
    table.add_row(['Longest Seq.length', max(sizes)])
    print(table)

def fasta_burst(fasta_file):
    '''Reports the length of each fasta sequence in the file. Takes filename as string'''
    my_file = open("Seq_length.tab","w")
   => for rec in SeqIO.parse(fasta_file,"fasta"):
        my_file.write(rec.id+'\t'+str(len(rec))+'\n')
    print("Length report written in Seq_length.tab")

def fasta_lendist(fasta_file):
    '''plot the distribution of sequence length as histogram. Takes filename as string'''
   => sizes = [len(rec) for rec in SeqIO.parse(fasta_file,"fasta")]
    count,bins,_ = pylab.hist(sizes, bins=100, log=True, histtype='step',color='red')
    pylab.title("%i seq with len: %i to %i bp (range)\nBin Max: %i seq around %i bp"%(len(sizes),min(sizes),max(sizes),count.max(),bins[np.argmax(count)]))
    pylab.xlabel("Sequence length (bp)")
    pylab.ylabel("Log Count")
    pylab.savefig("Sequence_length_distribution_plot.png")
    print("Plot saved as Sequence_length_distribution_plot.png")

fasta = 'filename.fa'
fasta_outlook(fasta)
fasta_lendist(fasta)

Проблема здесь в том, что во всех функциях я загружаю файл (=>) несколько раз. Можно ли загрузить файл только один раз глобально и использовать объект в последующих функциях? Принимает ли аргумент функции функцию вместо имени файла (строки)?

Ответы [ 2 ]

0 голосов
/ 04 сентября 2018

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

Сначала напишите функцию для загрузки соответствующих данных. Я думаю, что пара списков лучше, так как вы используете идентификаторы только один раз:

def load_file(filename):
    data = [(rec.id, len(rec)) for rec in SeqIO.parse(fasta_file, "fasta")]
    # Transpose the data into two lists instead of list of pairs
    return tuple(map(list, zip(*data)))

Теперь ваши вызовы функций должны выглядеть как

fasta = 'filename.fa'
ids, sizes = load_file(fasta)
fasta_outlook(sizes)
fasta_lendist(sizes)
fasta_burst(ids, sizes)

В fasta_outlook и fasta_lendist вы просто меняете имя входного параметра на sizes и удаляете понимание, которое вычисляет эти значения. В fasta_burst вы можете несколько упростить цикл:

def fasta_burst(ids, sizes):
'''Reports the length of each fasta sequence in the file. Takes filename as string'''
    with open("Seq_length.tab","w") as my_file:
        for id, rec in zip(ids, sizes):
            my_file.write('{}\t{}\n'.format(id, size))
    print("Length report written in Seq_length.tab")

Используйте блок with, убедитесь, что ваш файл закрыт после того, как вы покончили с ним. Вы вообще не закрывались раньше, и with имеет преимущество закрытия даже в случае ошибки.

0 голосов
/ 04 сентября 2018

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

fasta = 'filename.fa'
records = [record for record in SeqIO.parse(fasta,"fasta")]
fasta_outlook(records)
fasta_lendist(records

Одна из ваших функций теперь будет выглядеть так:

def fasta_outlook(fasta_records):
    sizes = [len(rec) for rec in fasta_records]
    table = PrettyTable(['Parameter', 'Stats'])
    table.add_row(['No. of Sequences', len(sizes)])
    table.add_row(['Shortest seq.length', min(sizes)])
    table.add_row(['Longest Seq.length', max(sizes)])
    print(table)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...