C 使用外部库kseq.h读取多个fasta序列

C 使用外部库kseq.h读取多个fasta序列,c,fasta,C,Fasta,我正在尝试使用外部头文件kseq.h从一个大的fasta文件(包含80000个fasta序列)中查找用户提供的5个id/name的fasta序列,如所示:。当我在for循环中运行程序时,我必须一次又一次地打开/关闭大的fasta文件(在代码中注释),这使得计算时间变慢。相反,如果我在循环外仅打开/关闭一次,则当程序遇到大fasta文件中不存在的条目(即到达文件末尾)时,程序将停止。有人能建议如何在不损失计算时间的情况下获得所有序列吗。代码是: #include <zlib.h> #i

我正在尝试使用外部头文件kseq.h从一个大的fasta文件(包含80000个fasta序列)中查找用户提供的5个id/name的fasta序列,如所示:。当我在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;
}   
#包括
#包括
#包括
#包括
#包括
#包括“外部库/kseq.h”
KSEQ_INIT(gzFile,gzread)
int main(int argc,char*argv[])
{
char gwidd_id[100];
kseq_t*seq;
int i=0,nFields=0,row=0,col=0;
int size=1000,flag1=0,l=0,index0=0;
printf(“正在打开文件%s\n”,argv[1]);
char**gi_id=(char**)malloc(sizeof(char*)*size);
对于(i=0;iname.s)==0)
{
fprintf(f1,“>%s\n”,gi_id[col]);
fprintf(f2,“>%s\n%s\n”,序号->名称,序号->序号);
flag1=1;
}
}
如果(flag1==0)
{
fprintf(f0,“%s\n”,gi_id[col]);
}
kseq_销毁(seq);
//gzclose(fpf);
}
gzclose(fpf);
fclose(f0);
fclose(f1);
fclose(f2);

对于(i=0;i您的问题似乎与您假设的有点不同。程序在尝试检索数据文件中不存在的序列后停止是因为它从未回放输入。因此,即使对于仅包含数据文件中存在的序列的查询列表,如果请求的序列ID为如果与数据文件的相对顺序不同,那么程序将无法找到某些序列(在查找之前列出的序列时,它将传递这些序列,而不会返回)

此外,我认为您观察到的时间节省可能来自于只对文件进行一次遍历,而不是(部分)为每个请求的序列传递密码,与其说是只打开一次,不如说是打开和关闭一个文件有点贵,但远不如从中读取几十或几百KB的字节

要直接回答您的问题,我认为您需要采取以下步骤:

  • kseq_init(seq)
    调用移到循环之前
  • kseq\u destroy(seq)
    调用移动到循环之后
  • 调用
    kseq\u倒带(seq)
    ,作为循环中的最后一条语句
  • 这将使您的程序再次正常运行,但这可能会消耗您几乎所有的时间节省,因为您将返回到从一开始就扫描每个请求序列的文件

    您正在使用的库似乎只支持顺序访问。因此,正确执行快速操作的最有效方法是反转逻辑:在外部循环中一次读取一个序列,在执行时测试每个序列,以查看它是否与任何请求的序列匹配


    假设所请求的序列列表将只包含几个条目,例如你的例子,你可能不需要做任何更好的匹配测试,而不仅仅是使用内环来测试每个请求的序列ID与当前的序列。如果查询列表可能更长,那么你可以考虑把它们放在一个哈希表或将其排序为与数据文件相同的顺序,以便能够更有效地测试匹配项。

    感谢您的建议。为了确认我正确理解您的答案,用户提供的输入并不总是顺序的,即P37592位于fasta_seq_uniprot.txt的92587行,而P70453位于li行ne编号92523,但如果我在for循环和before while循环中打开/关闭文件,则两者都匹配(如注释//)而且不匹配的条目B3GNT2根本不会被读取并写入文件xxx.txt,因此,无论条目的顺序如何,如果我按照用户的要求打开/关闭fasta_seq_uniprot.txt 5次,程序运行良好。我已经尝试过只打开/关闭fasta_seq_uniprot.txt一次,然后调用kseq_init(seq)就在while循环开始之前,将kseq_destroy(seq)放在循环结束之后(未注释的部分)……但它无法匹配最后的条目Q81U58和P70453,因为它无法匹配B3GNT2。