void analyse(t_atoms *atoms,t_blocka *gb,char ***gn,bool bASK,bool bVerb) { t_aa_names *aan; eRestp *restp; char *resnm; atom_id *aid; int nra; int i; size_t j; if (bVerb) printf("Analysing residue names:\n"); snew(restp,atoms->nres); aid=mk_aid(atoms,restp,etOther,&nra,TRUE); add_grp(gb,gn,nra,aid,"System"); sfree(aid); aan = get_aa_names(); for(i=0; (i<atoms->nres); i++) { resnm = *atoms->resinfo[i].name; if ((restp[i] == etOther) && is_protein(aan,resnm)) restp[i] = etProt; if (restp[i] == etOther) for(j=0; (j<NDNA); j++) { if (strcasecmp(Sugars[j],resnm) == 0) restp[i] = etDNA; } } p_status(atoms->nres,restp,bVerb); done_aa_names(&aan); /* Protein */ aid=mk_aid(atoms,restp,etProt,&nra,TRUE); if (nra > 0) analyse_prot(restp,atoms,gb,gn,bASK,bVerb); sfree(aid); /* Non-Protein */ aid=mk_aid(atoms,restp,etProt,&nra,FALSE); if ((nra > 0) && (nra < atoms->nr)) add_grp(gb,gn,nra,aid,"Non-Protein"); sfree(aid); /* DNA */ aid=mk_aid(atoms,restp,etDNA,&nra,TRUE); if (nra > 0) { add_grp(gb,gn,nra,aid,"DNA"); analyse_dna(restp,atoms,gb,gn,bASK,bVerb); } sfree(aid); /* Other */ analyse_other(restp,atoms,gb,gn,bASK,bVerb); aid=mk_aid(atoms,restp,etOther,&nra,TRUE); if ((nra > 0) && (nra < atoms->nr)) add_grp(gb,gn,nra,aid,"Other"); sfree(aid); sfree(restp); }
void analyse(t_atoms *atoms,t_blocka *gb,char ***gn,gmx_bool bASK,gmx_bool bVerb) { gmx_residuetype_t rt; char *resnm; atom_id *aid; const char ** restype; int nra; int i,k; size_t j; int ntypes; char * p; const char ** p_typename; int iwater,iion; int nwater,nion; int found; if (bVerb) { printf("Analysing residue names:\n"); } /* Create system group, every single atom */ snew(aid,atoms->nr); for(i=0;i<atoms->nr;i++) { aid[i]=i; } add_grp(gb,gn,atoms->nr,aid,"System"); sfree(aid); /* For every residue, get a pointer to the residue type name */ gmx_residuetype_init(&rt); snew(restype,atoms->nres); ntypes = 0; p_typename = NULL; for(i=0;i<atoms->nres;i++) { resnm = *atoms->resinfo[i].name; gmx_residuetype_get_type(rt,resnm,&(restype[i])); /* Note that this does not lead to a N*N loop, but N*K, where * K is the number of residue _types_, which is small and independent of N. */ found = 0; for(k=0;k<ntypes && !found;k++) { found = !strcmp(restype[i],p_typename[k]); } if(!found) { srenew(p_typename,ntypes+1); p_typename[ntypes++] = strdup(restype[i]); } } if (bVerb) { p_status(restype,atoms->nres,p_typename,ntypes); } for(k=0;k<ntypes;k++) { aid=mk_aid(atoms,restype,p_typename[k],&nra,TRUE); /* Check for special types to do fancy stuff with */ if(!gmx_strcasecmp(p_typename[k],"Protein") && nra>0) { sfree(aid); /* PROTEIN */ analyse_prot(restype,atoms,gb,gn,bASK,bVerb); /* Create a Non-Protein group */ aid=mk_aid(atoms,restype,"Protein",&nra,FALSE); if ((nra > 0) && (nra < atoms->nr)) { add_grp(gb,gn,nra,aid,"non-Protein"); } sfree(aid); } else if(!gmx_strcasecmp(p_typename[k],"Water") && nra>0) { add_grp(gb,gn,nra,aid,p_typename[k]); /* Add this group as 'SOL' too, for backward compatibility with older gromacs versions */ add_grp(gb,gn,nra,aid,"SOL"); sfree(aid); /* Solvent, create a negated group too */ aid=mk_aid(atoms,restype,"Water",&nra,FALSE); if ((nra > 0) && (nra < atoms->nr)) { add_grp(gb,gn,nra,aid,"non-Water"); } sfree(aid); } else if(nra>0) { /* Other groups */ add_grp(gb,gn,nra,aid,p_typename[k]); sfree(aid); analyse_other(restype,atoms,gb,gn,bASK,bVerb); } } sfree(p_typename); sfree(restype); gmx_residuetype_destroy(rt); /* Create a merged water_and_ions group */ iwater = -1; iion = -1; nwater = 0; nion = 0; for(i=0;i<gb->nr;i++) { if(!gmx_strcasecmp((*gn)[i],"Water")) { iwater = i; nwater = gb->index[i+1]-gb->index[i]; } else if(!gmx_strcasecmp((*gn)[i],"Ion")) { iion = i; nion = gb->index[i+1]-gb->index[i]; } } if(nwater>0 && nion>0) { srenew(gb->index,gb->nr+2); srenew(*gn,gb->nr+1); (*gn)[gb->nr] = strdup("Water_and_ions"); srenew(gb->a,gb->nra+nwater+nion); if(nwater>0) { for(i=gb->index[iwater];i<gb->index[iwater+1];i++) { gb->a[gb->nra++] = gb->a[i]; } } if(nion>0) { for(i=gb->index[iion];i<gb->index[iion+1];i++) { gb->a[gb->nra++] = gb->a[i]; } } gb->nr++; gb->index[gb->nr]=gb->nra; } }
static void analyse_prot(const char ** restype,t_atoms *atoms, t_blocka *gb,char ***gn,gmx_bool bASK,gmx_bool bVerb) { /* atomnames to be used in constructing index groups: */ static const char *pnoh[] = { "H" }; static const char *pnodum[] = { "MN1", "MN2", "MCB1", "MCB2", "MCG1", "MCG2", "MCD1", "MCD2", "MCE1", "MCE2", "MNZ1", "MNZ2" }; static const char *calpha[] = { "CA" }; static const char *bb[] = { "N","CA","C" }; static const char *mc[] = { "N","CA","C","O","O1","O2","OC1","OC2","OT","OXT" }; static const char *mcb[] = { "N","CA","CB","C","O","O1","O2","OC1","OC2","OT","OXT" }; static const char *mch[] = { "N","CA","C","O","O1","O2","OC1","OC2","OT","OXT", "H1","H2","H3","H" }; /* array of arrays of atomnames: */ static const char **chains[] = { NULL,pnoh,calpha,bb,mc,mcb,mch,mch,mch,pnodum }; #define NCH asize(chains) /* array of sizes of arrays of atomnames: */ const int sizes[NCH] = { 0, asize(pnoh), asize(calpha), asize(bb), asize(mc), asize(mcb), asize(mch), asize(mch), asize(mch), asize(pnodum) }; /* descriptive names of index groups */ const char *ch_name[NCH] = { "Protein", "Protein-H", "C-alpha", "Backbone", "MainChain", "MainChain+Cb", "MainChain+H", "SideChain", "SideChain-H", "Prot-Masses" }; /* construct index group containing (TRUE) or excluding (FALSE) given atom names */ const gmx_bool complement[NCH] = { TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE }; const int wholename[NCH] = { -1, 0,-1,-1,-1,-1,-1,-1, 11,-1 }; /* the index in wholename gives the first item in the arrays of * atomtypes that should be tested with 'gmx_strncasecmp' in stead of * gmx_strcasecmp, or -1 if all items should be tested with strcasecmp * This is comparable to using a '*' wildcard at the end of specific * atom names, but that is more involved to implement... */ /* only add index group if it differs from the specified one, specify -1 to always add group */ const int compareto[NCH] = { -1,-1,-1,-1,-1,-1,-1,-1,-1, 0 }; int n,j; atom_id *aid; int nra,nnpres,npres; gmx_bool match; char ndx_name[STRLEN],*atnm; int i; if (bVerb) { printf("Analysing Protein...\n"); } snew(aid,atoms->nr); /* calculate the number of protein residues */ npres=0; for(i=0; (i<atoms->nres); i++) if (!gmx_strcasecmp(restype[i],"Protein")) { npres++; } /* find matching or complement atoms */ for(i=0; (i<(int)NCH); i++) { nra=0; for(n=0; (n<atoms->nr); n++) { if (!gmx_strcasecmp(restype[atoms->atom[n].resind],"Protein")) { match=FALSE; for(j=0; (j<sizes[i]); j++) { /* skip digits at beginning of atomname, e.g. 1H */ atnm=*atoms->atomname[n]; while (isdigit(atnm[0])) atnm++; if ( (wholename[i]==-1) || (j<wholename[i]) ) { if (gmx_strcasecmp(chains[i][j],atnm) == 0) match=TRUE; } else { if (gmx_strncasecmp(chains[i][j],atnm,strlen(chains[i][j])) == 0) match=TRUE; } } if (match != complement[i]) aid[nra++]=n; } } /* if we want to add this group always or it differs from previous group, add it: */ if ( compareto[i] == -1 || !grp_cmp(gb,nra,aid,compareto[i]-i) ) add_grp(gb,gn,nra,aid,ch_name[i]); } if (bASK) { for(i=0; (i<(int)NCH); i++) { printf("Split %12s into %5d residues (y/n) ? ",ch_name[i],npres); if (gmx_ask_yesno(bASK)) { int resind; nra = 0; for(n=0;((atoms->atom[n].resind < npres) && (n<atoms->nr));) { resind = atoms->atom[n].resind; for(;((atoms->atom[n].resind==resind) && (n<atoms->nr));n++) { match=FALSE; for(j=0;(j<sizes[i]); j++) if (gmx_strcasecmp(chains[i][j],*atoms->atomname[n]) == 0) match=TRUE; if (match != complement[i]) aid[nra++]=n; } /* copy the residuename to the tail of the groupname */ if (nra > 0) { t_resinfo *ri; ri = &atoms->resinfo[resind]; sprintf(ndx_name,"%s_%s%d%c", ch_name[i],*ri->name,ri->nr,ri->ic==' ' ? '\0' : ri->ic); add_grp(gb,gn,nra,aid,ndx_name); nra = 0; } } } } printf("Make group with sidechain and C=O swapped (y/n) ? "); if (gmx_ask_yesno(bASK)) { /* Make swap sidechain C=O index */ int resind,hold; nra = 0; for(n=0;((atoms->atom[n].resind < npres) && (n<atoms->nr));) { resind = atoms->atom[n].resind; hold = -1; for(;((atoms->atom[n].resind==resind) && (n<atoms->nr));n++) if (strcmp("CA",*atoms->atomname[n]) == 0) { aid[nra++]=n; hold=nra; nra+=2; } else if (strcmp("C",*atoms->atomname[n]) == 0) { if (hold == -1) gmx_incons("Atom naming problem"); aid[hold]=n; } else if (strcmp("O",*atoms->atomname[n]) == 0) { if (hold == -1) gmx_incons("Atom naming problem"); aid[hold+1]=n; } else if (strcmp("O1",*atoms->atomname[n]) == 0) { if (hold == -1) gmx_incons("Atom naming problem"); aid[hold+1]=n; } else aid[nra++]=n; } /* copy the residuename to the tail of the groupname */ if (nra > 0) { add_grp(gb,gn,nra,aid,"SwapSC-CO"); nra = 0; } } } sfree(aid); }
static void analyse_other(const char ** restype,t_atoms *atoms, t_blocka *gb,char ***gn,gmx_bool bASK,gmx_bool bVerb) { restp_t *restp=NULL; char **attp=NULL; char *rname,*aname; atom_id *other_ndx,*aid,*aaid; int i,j,k,l,resind,naid,naaid,natp,nrestp=0; for(i=0; (i<atoms->nres); i++) { if (gmx_strcasecmp(restype[i],"Protein") && gmx_strcasecmp(restype[i],"DNA") && gmx_strcasecmp(restype[i],"RNA") && gmx_strcasecmp(restype[i],"Water")) { break; } } if (i < atoms->nres) { /* we have others */ if (bVerb) printf("Analysing residues not classified as Protein/DNA/RNA/Water and splitting into groups...\n"); snew(other_ndx,atoms->nr); for(k=0; (k<atoms->nr); k++) { resind = atoms->atom[k].resind; rname = *atoms->resinfo[resind].name; if (gmx_strcasecmp(restype[resind],"Protein") && gmx_strcasecmp(restype[resind],"DNA") && gmx_strcasecmp(restype[resind],"RNA") && gmx_strcasecmp(restype[resind],"Water")) { for(l=0; (l<nrestp); l++) if (strcmp(restp[l].rname,rname) == 0) break; if (l==nrestp) { srenew(restp,nrestp+1); restp[nrestp].rname = strdup(rname); restp[nrestp].bNeg = FALSE; restp[nrestp].gname = strdup(rname); nrestp++; } } } for(i=0; (i<nrestp); i++) { snew(aid,atoms->nr); naid=0; for(j=0; (j<atoms->nr); j++) { rname = *atoms->resinfo[atoms->atom[j].resind].name; if ((strcmp(restp[i].rname,rname) == 0 && !restp[i].bNeg) || (strcmp(restp[i].rname,rname) != 0 && restp[i].bNeg)) { aid[naid++] = j; } } add_grp(gb,gn,naid,aid,restp[i].gname); if (bASK) { printf("split %s into atoms (y/n) ? ",restp[i].gname); fflush(stdout); if (gmx_ask_yesno(bASK)) { natp=0; for(k=0; (k<naid); k++) { aname=*atoms->atomname[aid[k]]; for(l=0; (l<natp); l++) if (strcmp(aname,attp[l]) == 0) break; if (l == natp) { srenew(attp,++natp); attp[natp-1]=aname; } } if (natp > 1) { for(l=0; (l<natp); l++) { snew(aaid,naid); naaid=0; for(k=0; (k<naid); k++) { aname=*atoms->atomname[aid[k]]; if (strcmp(aname,attp[l])==0) aaid[naaid++]=aid[k]; } add_grp(gb,gn,naaid,aaid,attp[l]); sfree(aaid); } } sfree(attp); attp=NULL; } sfree(aid); } } sfree(other_ndx); } }
static void analyse_other(eRestp Restp[],t_atoms *atoms, t_blocka *gb,char ***gn,bool bASK,bool bVerb) { char **restp=NULL; char **attp=NULL; char *rname,*aname; atom_id *other_ndx,*aid,*aaid; int i,j,k,l,resnr,naid,naaid,natp,nrestp=0; for(i=0; (i<atoms->nres); i++) if (Restp[i] == etOther) break; if (i < atoms->nres) { /* we have others */ if (bVerb) printf("Analysing Other...\n"); snew(other_ndx,atoms->nr); for(k=0; (k<atoms->nr); k++) { resnr=atoms->atom[k].resnr; rname=*atoms->resname[resnr]; if (Restp[resnr] == etOther) { for(l=0; (l<nrestp); l++) if (strcmp(restp[l],rname) == 0) break; if (l==nrestp) { srenew(restp,++nrestp); restp[nrestp-1]=strdup(rname); } } } for(i=0; (i<nrestp); i++) { snew(aid,atoms->nr); naid=0; for(j=0; (j<atoms->nr); j++) { rname=*atoms->resname[atoms->atom[j].resnr]; if (strcmp(restp[i],rname) == 0) aid[naid++] = j; } add_grp(gb,gn,naid,aid,restp[i]); if (bASK) { printf("split %s into atoms (y/n) ? ",restp[i]); fflush(stdout); if (gmx_ask_yesno(bASK)) { natp=0; for(k=0; (k<naid); k++) { aname=*atoms->atomname[aid[k]]; for(l=0; (l<natp); l++) if (strcmp(aname,attp[l]) == 0) break; if (l == natp) { srenew(attp,++natp); attp[natp-1]=aname; } } if (natp > 1) { for(l=0; (l<natp); l++) { snew(aaid,naid); naaid=0; for(k=0; (k<naid); k++) { aname=*atoms->atomname[aid[k]]; if (strcmp(aname,attp[l])==0) aaid[naaid++]=aid[k]; } add_grp(gb,gn,naaid,aaid,attp[l]); sfree(aaid); } } sfree(attp); attp=NULL; } sfree(aid); } } sfree(other_ndx); } }
static void analyse_prot(const char ** restype, t_atoms *atoms, t_blocka *gb, char ***gn, gmx_bool bASK, gmx_bool bVerb) { /* lists of atomnames to be used in constructing index groups: */ static const char *pnoh[] = { "H", "HN" }; static const char *pnodum[] = { "MN1", "MN2", "MCB1", "MCB2", "MCG1", "MCG2", "MCD1", "MCD2", "MCE1", "MCE2", "MNZ1", "MNZ2" }; static const char *calpha[] = { "CA" }; static const char *bb[] = { "N", "CA", "C" }; static const char *mc[] = { "N", "CA", "C", "O", "O1", "O2", "OC1", "OC2", "OT", "OXT" }; static const char *mcb[] = { "N", "CA", "CB", "C", "O", "O1", "O2", "OC1", "OC2", "OT", "OXT" }; static const char *mch[] = { "N", "CA", "C", "O", "O1", "O2", "OC1", "OC2", "OT", "OXT", "H1", "H2", "H3", "H", "HN" }; static const t_gmx_help_make_index_group constructing_data[] = {{ NULL, 0, "Protein", TRUE, -1, -1}, { pnoh, asize(pnoh), "Protein-H", TRUE, 0, -1}, { calpha, asize(calpha), "C-alpha", FALSE, -1, -1}, { bb, asize(bb), "Backbone", FALSE, -1, -1}, { mc, asize(mc), "MainChain", FALSE, -1, -1}, { mcb, asize(mcb), "MainChain+Cb", FALSE, -1, -1}, { mch, asize(mch), "MainChain+H", FALSE, -1, -1}, { mch, asize(mch), "SideChain", TRUE, -1, -1}, { mch, asize(mch), "SideChain-H", TRUE, 11, -1}, { pnodum, asize(pnodum), "Prot-Masses", TRUE, -1, 0}, }; const int num_index_groups = asize(constructing_data); int n, j; atom_id *aid; int nra, nnpres, npres; gmx_bool match; char ndx_name[STRLEN], *atnm; int i; if (bVerb) { printf("Analysing Protein...\n"); } snew(aid, atoms->nr); /* calculate the number of protein residues */ npres = 0; for (i = 0; (i < atoms->nres); i++) { if (0 == gmx_strcasecmp(restype[i], "Protein")) { npres++; } } /* find matching or complement atoms */ for (i = 0; (i < (int)num_index_groups); i++) { nra = 0; for (n = 0; (n < atoms->nr); n++) { if (0 == gmx_strcasecmp(restype[atoms->atom[n].resind], "Protein")) { match = FALSE; for (j = 0; (j < constructing_data[i].num_defining_atomnames); j++) { /* skip digits at beginning of atomname, e.g. 1H */ atnm = *atoms->atomname[n]; while (isdigit(atnm[0])) { atnm++; } if ( (constructing_data[i].wholename == -1) || (j < constructing_data[i].wholename) ) { if (0 == gmx_strcasecmp(constructing_data[i].defining_atomnames[j], atnm)) { match = TRUE; } } else { if (0 == gmx_strncasecmp(constructing_data[i].defining_atomnames[j], atnm, strlen(constructing_data[i].defining_atomnames[j]))) { match = TRUE; } } } if (constructing_data[i].bTakeComplement != match) { aid[nra++] = n; } } } /* if we want to add this group always or it differs from previous group, add it: */ if (-1 == constructing_data[i].compareto || !grp_cmp(gb, nra, aid, constructing_data[i].compareto-i) ) { add_grp(gb, gn, nra, aid, constructing_data[i].group_name); } } if (bASK) { for (i = 0; (i < (int)num_index_groups); i++) { printf("Split %12s into %5d residues (y/n) ? ", constructing_data[i].group_name, npres); if (gmx_ask_yesno(bASK)) { int resind; nra = 0; for (n = 0; ((atoms->atom[n].resind < npres) && (n < atoms->nr)); ) { resind = atoms->atom[n].resind; for (; ((atoms->atom[n].resind == resind) && (n < atoms->nr)); n++) { match = FALSE; for (j = 0; (j < constructing_data[i].num_defining_atomnames); j++) { if (0 == gmx_strcasecmp(constructing_data[i].defining_atomnames[j], *atoms->atomname[n])) { match = TRUE; } } if (constructing_data[i].bTakeComplement != match) { aid[nra++] = n; } } /* copy the residuename to the tail of the groupname */ if (nra > 0) { t_resinfo *ri; ri = &atoms->resinfo[resind]; sprintf(ndx_name, "%s_%s%d%c", constructing_data[i].group_name, *ri->name, ri->nr, ri->ic == ' ' ? '\0' : ri->ic); add_grp(gb, gn, nra, aid, ndx_name); nra = 0; } } } } printf("Make group with sidechain and C=O swapped (y/n) ? "); if (gmx_ask_yesno(bASK)) { /* Make swap sidechain C=O index */ int resind, hold; nra = 0; for (n = 0; ((atoms->atom[n].resind < npres) && (n < atoms->nr)); ) { resind = atoms->atom[n].resind; hold = -1; for (; ((atoms->atom[n].resind == resind) && (n < atoms->nr)); n++) { if (strcmp("CA", *atoms->atomname[n]) == 0) { aid[nra++] = n; hold = nra; nra += 2; } else if (strcmp("C", *atoms->atomname[n]) == 0) { if (hold == -1) { gmx_incons("Atom naming problem"); } aid[hold] = n; } else if (strcmp("O", *atoms->atomname[n]) == 0) { if (hold == -1) { gmx_incons("Atom naming problem"); } aid[hold+1] = n; } else if (strcmp("O1", *atoms->atomname[n]) == 0) { if (hold == -1) { gmx_incons("Atom naming problem"); } aid[hold+1] = n; } else { aid[nra++] = n; } } } /* copy the residuename to the tail of the groupname */ if (nra > 0) { add_grp(gb, gn, nra, aid, "SwapSC-CO"); nra = 0; } } } sfree(aid); }
static int print_data(t_topology *top, t_trxframe *fr, t_pbc *pbc, int nr, gmx_ana_selection_t *sel[], void *data) { t_dsdata *d = (t_dsdata *)data; int g, i, b, mask; real normfac; char buf2[100],*buf,*nl; static int bFirstFrame=1; /* Write the sizes of the groups, possibly normalized */ if (d->sfp) { fprintf(d->sfp, "%11.3f", fr->time); for (g = 0; g < nr; ++g) { normfac = d->bFracNorm ? 1.0 / sel[g]->cfrac : 1.0; fprintf(d->sfp, " %8.3f", sel[g]->p.nr * normfac / d->size[g]); } fprintf(d->sfp, "\n"); } /* Write the covered fraction */ if (d->cfp) { fprintf(d->cfp, "%11.3f", fr->time); for (g = 0; g < nr; ++g) { fprintf(d->cfp, " %6.4f", sel[g]->cfrac); } fprintf(d->cfp, "\n"); } /* Write the actual indices */ if (d->ifp) { if (!d->bDump) { fprintf(d->ifp, "%11.3f", fr->time); } for (g = 0; g < nr; ++g) { if (!d->bDump) { fprintf(d->ifp, " %d", sel[g]->p.nr); } for (i = 0; i < sel[g]->p.nr; ++i) { if (sel[g]->p.m.type == INDEX_RES && d->routt[0] == 'n') { fprintf(d->ifp, " %d", top->atoms.resinfo[sel[g]->p.m.mapid[i]].nr); } else { fprintf(d->ifp, " %d", sel[g]->p.m.mapid[i]+1); } } } fprintf(d->ifp, "\n"); } if (d->block) { for (g = 0; g < nr; ++g) { if (sel[g]->bDynamic || bFirstFrame) { buf = strdup(sel[g]->name); while ((nl = strchr(buf, ' ')) != NULL) { *nl = '_'; } if (sel[g]->bDynamic) { sprintf(buf2, "_%.3f", fr->time); srenew(buf, strlen(buf) + strlen(buf2) + 1); strcat(buf, buf2); } add_grp(d->block, &d->gnames, sel[g]->p.nr, sel[g]->p.m.mapid, buf); sfree(buf); } } } /* Write masks */ if (d->mfp) { gmx_ana_indexmap_update(d->mmap, sel[0]->g, TRUE); if (!d->bDump) { fprintf(d->mfp, "%11.3f", fr->time); } for (b = 0; b < d->mmap->nr; ++b) { mask = (d->mmap->refid[b] == -1 ? 0 : 1); fprintf(d->mfp, d->bDump ? "%d\n" : " %d", mask); } if (!d->bDump) { fprintf(d->mfp, "\n"); } } bFirstFrame = 0; return 0; }