我正在尝试使用外部头文件kseq.h找到用户从大型fasta文件(包含80000个fasta序列)提供的5个ID /名称的fasta序列,如:http://lh3lh3.users.sourceforge.net/kseq.shtml。当我在for循环中运行程序时,我必须一次又一次地打开/关闭大的fasta文件(在代码中注释),这使得计算时间变慢。相反,如果我只在循环外打开/关闭一次,程序会在遇到大型fasta文件中不存在的条目时停止。它到达文件的末尾。谁能建议如何在不损失计算时间的情况下获得所有序列。代码是:
#include <zlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "ext_libraries/kseq.h"
KSEQ_INIT(gzFile, gzread)
int main(int argc, char *argv[])
{
char gwidd_ids[100];
kseq_t *seq;
int i=0, nFields=0, row=0, col=0;
int size=1000, flag1=0, l=0, index0=0;
printf("Opening file %s\n", argv[1]);
char **gi_ids=(char **)malloc(sizeof(char *)*size);
for(i=0;i<size;i++)
{
gi_ids[i]=(char *)malloc(sizeof(char)*50);
}
FILE *fp_inp = fopen(argv[1], "r");
while(fscanf(fp_inp, "%s", gwidd_ids) == 1)
{
printf("%s\n", gwidd_ids);
strcpy(gi_ids[index0], gwidd_ids);
index0++;
}
fclose(fp_inp);
FILE *f0 = fopen("xxx.txt", "w");
FILE *f1 = fopen("yyy.txt", "w");
FILE *f2 = fopen("zzz", "w");
FILE *instream = NULL;
instream = fopen("fasta_seq_uniprot.txt", "r");
gzFile fpf = gzdopen(fileno(instream), "r");
for(col=0;col<index0;col++)
{
flag1=0;
// FILE *instream = NULL;
// instream = fopen("fasta_seq_nr_uniprot.txt", "r");
// gzFile fpf = gzdopen(fileno(instream), "r");
kseq_t *seq = kseq_init(fpf);
while((kseq_read(seq)) >= 0 && flag1 == 0)
{
if(strcasecmp(gi_ids[col], seq->name.s) == 0)
{
fprintf(f1, ">%s\n", gi_ids[col]);
fprintf(f2, ">%s\n%s\n", seq->name.s, seq->seq.s);
flag1 = 1;
}
}
if(flag1 == 0)
{
fprintf(f0, "%s\n", gi_ids[col]);
}
kseq_destroy(seq);
// gzclose(fpf);
}
gzclose(fpf);
fclose(f0);
fclose(f1);
fclose(f2);
for(i=0;i<size;i++)
{
free(gi_ids[i]);
}
free(gi_ids);
return 0;
}
inputfile(fasta_seq_uniprot.txt)的一些示例是:
P21306 MSAWRKAGISYAAYLNVAAQAIRSSLKTELQTASVLNRSQTDAFYTQYKNGTAASEPTPITK P38077 MLSRIVSNNATRSVMCHQAQVGILYKTNPVRTYATLKEVEMRLKSIKNIEKITKTMKIVASTRLSKAEKAKISAKKMD ----------- -----------
用户输入文件是 P37592 \ n Q8IUX1 \ n B3GNT2 \ n Q81U58 \ n P70453 \ n
答案 0 :(得分:1)
您的问题与您想象的有点不同。程序在尝试检索数据文件中不存在的序列后停止,这是因为它永远不会重新输入输入。因此,即使对于仅包含数据文件中存在的序列的查询列表,如果请求的序列ID与数据文件的顺序不相同,那么程序将无法找到某些序列(它将通过它们在寻找先前列出的序列时,永远不要返回。)
此外,我认为你观察到的节省时间可能来自于只通过文件一次,而不是每个请求序列的(部分)传递,而不是只打开一次。打开和关闭文件有点贵,但远不如从中读取数十或数百千字节那么昂贵。
要直接回答您的问题,我认为您需要采取以下措施:
kseq_init(seq)
调用移至循环之前。kseq_destroy(seq)
调用移至循环之后。kseq_rewind(seq)
作为循环中的最后一个语句。这应该会使您的程序再次正常,但它可能会耗尽您所有的时间节省,因为您将返回从每个请求的序列开始扫描文件。
您使用的库似乎仅支持顺序访问。因此,快速完成和工作的最有效方法是反转逻辑:在外部循环中一次读取一个序列,测试每个序列,看看它是否匹配所请求的任何。
假设所请求序列的列表只包含几个条目,例如您的示例,您可能不需要对匹配进行更好的测试,而不仅仅使用内部循环来测试每个请求的序列ID与当时 - 当前序列。但是,如果查询列表可能要长得多,那么您可以考虑将它们放在哈希表中,或者将它们排序为与数据文件相同的顺序,以便更有效地测试匹配。