Ejemplo n.º 1
0
int write_trxframe(t_trxstatus *status,t_trxframe *fr,gmx_conect gc)
{
  char title[STRLEN];
  real prec;

  if (fr->bPrec)
    prec = fr->prec;
  else
    prec = 1000.0;

  switch (gmx_fio_getftp(status->fio)) {
  case efTRJ:
  case efTRR:
    break;
  default:
    if (!fr->bX)
      gmx_fatal(FARGS,"Need coordinates to write a %s trajectory",
		  ftp2ext(gmx_fio_getftp(status->fio)));
    break;
  }

  switch (gmx_fio_getftp(status->fio)) {
  case efXTC:
    write_xtc(status->fio,fr->natoms,fr->step,fr->time,fr->box,fr->x,prec);
    break;
  case efTRJ:
  case efTRR:  
    fwrite_trn(status->fio,fr->step,fr->time,fr->lambda,fr->box,fr->natoms,
	       fr->bX ? fr->x:NULL,fr->bV ? fr->v:NULL ,fr->bF ? fr->f:NULL);
    break;
  case efGRO:
  case efPDB:
  case efBRK:
  case efENT:
    if (!fr->bAtoms)
      gmx_fatal(FARGS,"Can not write a %s file without atom names",
		  ftp2ext(gmx_fio_getftp(status->fio)));
    sprintf(title,"frame t= %.3f",fr->time);
    if (gmx_fio_getftp(status->fio) == efGRO)
      write_hconf_p(gmx_fio_getfp(status->fio),title,fr->atoms,
		    prec2ndec(prec),fr->x,fr->bV ? fr->v : NULL,fr->box);
    else
      write_pdbfile(gmx_fio_getfp(status->fio),title,
		    fr->atoms,fr->x,fr->bPBC ? fr->ePBC : -1,fr->box,
		    ' ',fr->step,gc,TRUE);
    break;
  case efG87:
    write_gms(gmx_fio_getfp(status->fio),fr->natoms,fr->x,fr->box);
    break;
  case efG96:
    write_g96_conf(gmx_fio_getfp(status->fio),fr,-1,NULL); 
    break;
  default:
    gmx_fatal(FARGS,"Sorry, write_trxframe can not write %s",
		ftp2ext(gmx_fio_getftp(status->fio)));
    break;
  }

  return 0;
}
Ejemplo n.º 2
0
void write_conf_p(char *outfile, char *title, t_atoms *atoms, int pr,
		  rvec *x, rvec *v,matrix box)
{
  FILE *out;

  out=gmx_fio_fopen(outfile,"w");
  write_hconf_p(out,title,atoms,pr,x,v,box);

  gmx_fio_fclose (out);
}
Ejemplo n.º 3
0
int write_trxframe(t_trxstatus *status, t_trxframe *fr, gmx_conect gc)
{
    char title[STRLEN];
    real prec;

    if (fr->bPrec)
    {
        prec = fr->prec;
    }
    else
    {
        prec = 1000.0;
    }

    if (status->tng)
    {
        gmx_tng_set_compression_precision(status->tng, prec);
        write_tng_frame(status, fr);

        return 0;
    }

    switch (gmx_fio_getftp(status->fio))
    {
        case efTRR:
            break;
        default:
            if (!fr->bX)
            {
                gmx_fatal(FARGS, "Need coordinates to write a %s trajectory",
                          ftp2ext(gmx_fio_getftp(status->fio)));
            }
            break;
    }

    switch (gmx_fio_getftp(status->fio))
    {
        case efXTC:
            write_xtc(status->fio, fr->natoms, fr->step, fr->time, fr->box, fr->x, prec);
            break;
        case efTRR:
            gmx_trr_write_frame(status->fio, fr->step, fr->time, fr->lambda, fr->box, fr->natoms,
                                fr->bX ? fr->x : nullptr, fr->bV ? fr->v : nullptr, fr->bF ? fr->f : nullptr);
            break;
        case efGRO:
        case efPDB:
        case efBRK:
        case efENT:
            if (!fr->bAtoms)
            {
                gmx_fatal(FARGS, "Can not write a %s file without atom names",
                          ftp2ext(gmx_fio_getftp(status->fio)));
            }
            sprintf(title, "frame t= %.3f", fr->time);
            if (gmx_fio_getftp(status->fio) == efGRO)
            {
                write_hconf_p(gmx_fio_getfp(status->fio), title, fr->atoms,
                              fr->x, fr->bV ? fr->v : nullptr, fr->box);
            }
            else
            {
                write_pdbfile(gmx_fio_getfp(status->fio), title,
                              fr->atoms, fr->x, fr->bPBC ? fr->ePBC : -1, fr->box,
                              ' ', fr->step, gc, TRUE);
            }
            break;
        case efG96:
            write_g96_conf(gmx_fio_getfp(status->fio), title, fr, -1, nullptr);
            break;
        default:
            gmx_fatal(FARGS, "Sorry, write_trxframe can not write %s",
                      ftp2ext(gmx_fio_getftp(status->fio)));
            break;
    }

    return 0;
}
Ejemplo n.º 4
0
int main(int argc,char *argv[])
{
    const char *desc[] = {
	"[TT]do_multiprot[tt] ", 
	"reads a trajectory file and aligns it to a reference structure  ",
	"each time frame",
	"calling the multiprot program. This allows you to use a reference",
	"structure whose sequence is different than that of the protein in the ",
	"trajectory, since the alignment is based on the geometry, not sequence.",
	"The output of [TT]do_multiprot[tt] includes the rmsd and the number of residues",
	"on which it was calculated.",
	"[PAR]",
	"An aligned trajectory file is generated with the [TT]-ox[tt] option.[PAR]",
	"With the [TT]-cr[tt] option, the number of hits in the alignment is given",
	"per residue. This number can be between 0 and the number of frames, and",
	"indicates the structural conservation of this residue.[PAR]",
	"If you do not have the [TT]multiprot[tt] program, get it. [TT]do_multiprot[tt] assumes", 
	"that the [TT]multiprot[tt] executable is [TT]/usr/local/bin/multiprot[tt]. If this is ",
	"not the case, then you should set an environment variable [BB]MULTIPROT[bb]", 
	"pointing to the [TT]multiprot[tt] executable, e.g.: [PAR]",
	"[TT]setenv MULTIPROT /usr/MultiProtInstall/multiprot.Linux[tt][PAR]",
	"Note that at the current implementation only binary alignment (your",
	"molecule to a reference) is supported. In addition, note that the ",
	"by default [TT]multiprot[tt] aligns the two proteins on their C-alpha carbons.",
	"and that this depends on the [TT]multiprot[tt] parameters which are not dealt ",
	"with here. Thus, the C-alpha carbons is expected to give the same "
	"results as choosing the whole protein and will be slightly faster.[PAR]",
	"For information about [TT]multiprot[tt], see:",
	"http://bioinfo3d.cs.tau.ac.il/MultiProt/.[PAR]"
    };
    static bool bVerbose;
    t_pargs pa[] = {
	{ "-v",  FALSE, etBOOL, {&bVerbose},
	  "HIDDENGenerate miles of useless information" }
    };
  
    const char *bugs[] = { 
	"The program is very slow, since multiprot is run externally"
    };
  
    t_trxstatus *status;
    t_trxstatus *trxout=NULL;
    FILE        *tapein,*fo,*frc,*tmpf,*out=NULL,*fres=NULL;
    const char  *fnRef;
    const char  *fn="2_sol.res";
    t_topology  top;
    int         ePBC;
    t_atoms     *atoms,ratoms,useatoms;
    t_trxframe  fr;
    t_pdbinfo   p;
    int         nres,nres2,nr0;
    real        t;
    int         i,j,natoms,nratoms,nframe=0,model_nr=-1;
    int         cur_res,prev_res;
    int         nout;
    t_countres  *countres=NULL;
    matrix      box,rbox;
    int         gnx;
    char        *grpnm,*ss_str; 
    atom_id     *index;
    rvec        *xp,*x,*xr;
    char        pdbfile[32],refpdb[256],title[256],rtitle[256],filemode[5];
    char        out_title[256];
    char        multiprot[256],*mptr;
    int         ftp;
    int         outftp=-1;
    real        rmsd;
    bool        bTrjout,bCountres;
    const char  *TrjoutFile=NULL;
    output_env_t oenv;
    static rvec translation={0,0,0},rotangles={0,0,0};
    gmx_rmpbc_t gpbc=NULL;
    
    t_filenm   fnm[] = {
	{ efTRX, "-f",   NULL,      ffREAD },
	{ efTPS, NULL,   NULL,      ffREAD },
	{ efNDX, NULL,   NULL,      ffOPTRD },
	{ efSTX, "-r",   NULL     , ffREAD },
	{ efXVG, "-o",  "rmss",     ffWRITE },
	{ efXVG, "-rc", "rescount", ffWRITE},
	{ efXVG, "-cr", "countres", ffOPTWR},
	{ efTRX, "-ox", "aligned",  ffOPTWR }
    };
#define NFILE asize(fnm)
    
    CopyRight(stderr,argv[0]);
    parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_TIME_UNIT,
		      NFILE,fnm, asize(pa),pa, asize(desc),desc,
		      asize(bugs),bugs,&oenv
	);
    fnRef=opt2fn("-r",NFILE,fnm);
    bTrjout = opt2bSet("-ox",NFILE,fnm);
    bCountres=  opt2bSet("-cr",NFILE,fnm);
    
    if (bTrjout) {
	TrjoutFile = opt2fn_null("-ox",NFILE,fnm);
    }
    
    read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xp,NULL,box,FALSE);
    gpbc = gmx_rmpbc_init(&top.idef,ePBC,top.atoms.nr,box);
    atoms=&(top.atoms);

    ftp=fn2ftp(fnRef);
 
    get_stx_coordnum(fnRef,&nratoms);
    init_t_atoms(&ratoms,nratoms,TRUE);  
    snew(xr,nratoms);
    read_stx_conf(fnRef,rtitle,&ratoms,xr,NULL,&ePBC,rbox);
    
    if (bVerbose) {
	fprintf(stderr,"Read %d atoms\n",atoms->nr); 
	fprintf(stderr,"Read %d reference atoms\n",ratoms.nr); 
    }
    if (bCountres) {
	snew(countres,ratoms.nres);
	j=0;
	cur_res=0;
	for (i=0;i<ratoms.nr;i++) {
	    prev_res=cur_res;
	    cur_res=ratoms.atom[i].resind;
	    if (cur_res != prev_res) {
		countres[j].resnr=cur_res;
		countres[j].count=0;
		j++;
	    }
	}
    }
    get_index(atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&gnx,&index,&grpnm);
    nres=0;
    nr0=-1;
    for(i=0; (i<gnx); i++) {
	if (atoms->atom[index[i]].resind != nr0) {
	    nr0=atoms->atom[index[i]].resind;
	    nres++;
	}
    }
    fprintf(stderr,"There are %d residues in your selected group\n",nres);
    
    strcpy(pdbfile,"ddXXXXXX");
    gmx_tmpnam(pdbfile);
    if ((tmpf = fopen(pdbfile,"w")) == NULL) {
	sprintf(pdbfile,"%ctmp%cfilterXXXXXX",DIR_SEPARATOR,DIR_SEPARATOR);
	gmx_tmpnam(pdbfile);
	if ((tmpf = fopen(pdbfile,"w")) == NULL) {
	    gmx_fatal(FARGS,"Can not open tmp file %s",pdbfile);
	}
    }
    else {
	gmx_ffclose(tmpf);
    }

    if (ftp != efPDB) {
	strcpy(refpdb,"ddXXXXXX");
	gmx_tmpnam(refpdb);
	strcat(refpdb,".pdb");
	write_sto_conf(refpdb,rtitle,&ratoms,xr,NULL,ePBC,rbox);
    }
    else {
	strcpy(refpdb,fnRef);
    }

    if ((mptr=getenv("MULTIPROT")) == NULL) {
	mptr="/usr/local/bin/multiprot";
    }
    if (!gmx_fexist(mptr)) {
	gmx_fatal(FARGS,"MULTIPROT executable (%s) does not exist (use setenv MULTIPROT)",
		  mptr);
    }
    sprintf (multiprot,"%s %s %s > /dev/null %s",
	     mptr, refpdb, pdbfile, "2> /dev/null");
    
    if (bVerbose)
	fprintf(stderr,"multiprot cmd='%s'\n",multiprot);
    
    if (!read_first_frame(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&fr,TRX_READ_X)) 
      	gmx_fatal(FARGS,"Could not read a frame from %s",ftp2fn(efTRX,NFILE,fnm));
    natoms = fr.natoms;

    if (bTrjout) {
	nout=natoms;
	/* open file now */
	outftp=fn2ftp(TrjoutFile);
	if (bVerbose)
	    fprintf(stderr,"Will write %s: %s\n",ftp2ext(ftp),ftp2desc(outftp));
	strcpy(filemode,"w");
	switch (outftp) {
	    case efXTC:
	    case efG87:
	    case efTRR:
	    case efTRJ:
		out=NULL;
		trxout = open_trx(TrjoutFile,filemode);
		break;
	    case efGRO:
	    case efG96:
	    case efPDB:
		/* Make atoms struct for output in GRO or PDB files */
		/* get memory for stuff to go in pdb file */
		init_t_atoms(&useatoms,nout,FALSE);
		sfree(useatoms.resinfo);
		useatoms.resinfo=atoms->resinfo;
		for(i=0;(i<nout);i++) {
		    useatoms.atomname[i]=atoms->atomname[i];
		    useatoms.atom[i]=atoms->atom[i];
		    useatoms.nres=max(useatoms.nres,useatoms.atom[i].resind+1);
		}
		useatoms.nr=nout;
		out=gmx_ffopen(TrjoutFile,filemode);
		break;
	}
    }
    
    if (natoms > atoms->nr) {
	gmx_fatal(FARGS,"\nTrajectory does not match topology!");
    }
    if (gnx > natoms) {
	gmx_fatal(FARGS,"\nTrajectory does not match selected group!");
    }

    fo = xvgropen(opt2fn("-o",NFILE,fnm),"RMSD","Time (ps)","RMSD (nm)",oenv);
    frc = xvgropen(opt2fn("-rc",NFILE,fnm),"Number of Residues in the alignment","Time (ps)","Residues",oenv);
    
    do {
	t = output_env_conv_time(oenv,fr.time);
	gmx_rmpbc(gpbc,natoms,fr.box,fr.x);
	tapein=gmx_ffopen(pdbfile,"w");
	write_pdbfile_indexed(tapein,NULL,atoms,fr.x,ePBC,fr.box,' ',-1,gnx,index,NULL,TRUE); 
	gmx_ffclose(tapein);
	system(multiprot);
	remove(pdbfile);
	process_multiprot_output(fn, &rmsd, &nres2,rotangles,translation,bCountres,countres);
	fprintf(fo,"%12.7f",t);
	fprintf(fo," %12.7f\n",rmsd);
	fprintf(frc,"%12.7f",t);
	fprintf(frc,"%12d\n",nres2);
	if (bTrjout) {
	    rotate_conf(natoms,fr.x,NULL,rotangles[XX],rotangles[YY],rotangles[ZZ]);
	    for(i=0; i<natoms; i++) {
		rvec_inc(fr.x[i],translation);
	    }
	    switch(outftp) {
		case efTRJ:
		case efTRR:
		case efG87:
		case efXTC:
		    write_trxframe(trxout,&fr,NULL);
		    break;
		case efGRO:
		case efG96:
		case efPDB:
		    sprintf(out_title,"Generated by do_multiprot : %s t= %g %s",
			    title,output_env_conv_time(oenv,fr.time),output_env_get_time_unit(oenv));
		    switch(outftp) {
			case efGRO: 
			    write_hconf_p(out,out_title,&useatoms,prec2ndec(fr.prec),
					  fr.x,NULL,fr.box);
			    break;
			case efPDB:
			    fprintf(out,"REMARK    GENERATED BY DO_MULTIPROT\n");
			    sprintf(out_title,"%s t= %g %s",title,output_env_conv_time(oenv,fr.time),output_env_get_time_unit(oenv));
			    /* if reading from pdb, we want to keep the original 
			       model numbering else we write the output frame
			       number plus one, because model 0 is not allowed in pdb */
			    if (ftp==efPDB && fr.step > model_nr) {
				model_nr = fr.step;
			    }
			    else {
				model_nr++;
			    }
			    write_pdbfile(out,out_title,&useatoms,fr.x,ePBC,fr.box,' ',model_nr,NULL,TRUE);
			    break;
			case efG96:
			    fr.title = out_title;
			    fr.bTitle = (nframe == 0);
			    fr.bAtoms = FALSE;
			    fr.bStep = TRUE;
			    fr.bTime = TRUE;
			    write_g96_conf(out,&fr,-1,NULL);
		    }
		    break;
	    }
	}
	nframe++;
    } while(read_next_frame(oenv,status,&fr));
    if (bCountres) {
	fres=  xvgropen(opt2fn("-cr",NFILE,fnm),"Number of frames in which the residues are aligned to","Residue","Number",oenv);
	for (i=0;i<ratoms.nres;i++) {
	    fprintf(fres,"%10d  %12d\n",countres[i].resnr,countres[i].count);
	}
	gmx_ffclose(fres);
    }
    gmx_ffclose(fo);
    gmx_ffclose(frc);
    fprintf(stderr,"\n");
    close_trj(status);
    if (trxout != NULL) {
	close_trx(trxout);
    }
    else if (out != NULL) {
	gmx_ffclose(out);
    }
    view_all(oenv,NFILE, fnm);
    sfree(xr);
    if (bCountres) {
	sfree(countres);
    }
    free_t_atoms(&ratoms,TRUE);
    if (bTrjout) {
	if (outftp==efPDB || outftp==efGRO || outftp==efG96) {
	    free_t_atoms(&useatoms,TRUE);
	}
    }
    gmx_thanx(stderr);
    return 0;
}
Ejemplo n.º 5
0
int gmx_confrms(int argc, char *argv[])
{
    const char     *desc[] = {
        "[TT]g_confrms[tt] computes the root mean square deviation (RMSD) of two",
        "structures after least-squares fitting the second structure on the first one.",
        "The two structures do NOT need to have the same number of atoms,",
        "only the two index groups used for the fit need to be identical.",
        "With [TT]-name[tt] only matching atom names from the selected groups",
        "will be used for the fit and RMSD calculation. This can be useful ",
        "when comparing mutants of a protein.",
        "[PAR]",
        "The superimposed structures are written to file. In a [TT].pdb[tt] file",
        "the two structures will be written as separate models",
        "(use [TT]rasmol -nmrpdb[tt]). Also in a [TT].pdb[tt] file, B-factors",
        "calculated from the atomic MSD values can be written with [TT]-bfac[tt].",
    };
    static gmx_bool bOne  = FALSE, bRmpbc = FALSE, bMW = TRUE, bName = FALSE,
                    bBfac = FALSE, bFit = TRUE, bLabel = FALSE;

    t_pargs  pa[] = {
        { "-one", FALSE, etBOOL, {&bOne},   "Only write the fitted structure to file" },
        { "-mw",  FALSE, etBOOL, {&bMW},    "Mass-weighted fitting and RMSD" },
        { "-pbc", FALSE, etBOOL, {&bRmpbc}, "Try to make molecules whole again" },
        { "-fit", FALSE, etBOOL, {&bFit},
          "Do least squares superposition of the target structure to the reference" },
        { "-name", FALSE, etBOOL, {&bName},
          "Only compare matching atom names" },
        { "-label", FALSE, etBOOL, {&bLabel},
          "Added chain labels A for first and B for second structure"},
        { "-bfac", FALSE, etBOOL, {&bBfac},
          "Output B-factors from atomic MSD values" }
    };
    t_filenm fnm[] = {
        { efTPS, "-f1",  "conf1.gro", ffREAD  },
        { efSTX, "-f2",  "conf2",     ffREAD  },
        { efSTO, "-o",   "fit.pdb",   ffWRITE },
        { efNDX, "-n1", "fit1.ndx",  ffOPTRD },
        { efNDX, "-n2", "fit2.ndx",  ffOPTRD },
        { efNDX, "-no", "match.ndx", ffOPTWR }
    };
#define NFILE asize(fnm)

    /* the two structure files */
    const char  *conf1file, *conf2file, *matchndxfile, *outfile;
    FILE        *fp;
    char         title1[STRLEN], title2[STRLEN], *name1, *name2;
    t_topology  *top1, *top2;
    int          ePBC1, ePBC2;
    t_atoms     *atoms1, *atoms2;
    int          warn = 0;
    atom_id      at;
    real        *w_rls, mass, totmass;
    rvec        *x1, *v1, *x2, *v2, *fit_x;
    matrix       box1, box2;

    output_env_t oenv;

    /* counters */
    int     i, j, m;

    /* center of mass calculation */
    real    tmas1, tmas2;
    rvec    xcm1, xcm2;

    /* variables for fit */
    char    *groupnames1, *groupnames2;
    int      isize1, isize2;
    atom_id *index1, *index2;
    real     rms, msd, minmsd, maxmsd;
    real    *msds;


    parse_common_args(&argc, argv, PCA_BE_NICE | PCA_CAN_VIEW,
                      NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv);
    matchndxfile = opt2fn_null("-no", NFILE, fnm);
    conf1file    = ftp2fn(efTPS, NFILE, fnm);
    conf2file    = ftp2fn(efSTX, NFILE, fnm);

    /* reading reference structure from first structure file */
    fprintf(stderr, "\nReading first structure file\n");
    snew(top1, 1);
    read_tps_conf(conf1file, title1, top1, &ePBC1, &x1, &v1, box1, TRUE);
    atoms1 = &(top1->atoms);
    fprintf(stderr, "%s\nContaining %d atoms in %d residues\n",
            title1, atoms1->nr, atoms1->nres);

    if (bRmpbc)
    {
        rm_gropbc(atoms1, x1, box1);
    }

    fprintf(stderr, "Select group from first structure\n");
    get_index(atoms1, opt2fn_null("-n1", NFILE, fnm),
              1, &isize1, &index1, &groupnames1);
    printf("\n");

    if (bFit && (isize1 < 3))
    {
        gmx_fatal(FARGS, "Need >= 3 points to fit!\n");
    }

    /* reading second structure file */
    fprintf(stderr, "\nReading second structure file\n");
    snew(top2, 1);
    read_tps_conf(conf2file, title2, top2, &ePBC2, &x2, &v2, box2, TRUE);
    atoms2 = &(top2->atoms);
    fprintf(stderr, "%s\nContaining %d atoms in %d residues\n",
            title2, atoms2->nr, atoms2->nres);

    if (bRmpbc)
    {
        rm_gropbc(atoms2, x2, box2);
    }

    fprintf(stderr, "Select group from second structure\n");
    get_index(atoms2, opt2fn_null("-n2", NFILE, fnm),
              1, &isize2, &index2, &groupnames2);

    if (bName)
    {
        find_matching_names(&isize1, index1, atoms1, &isize2, index2, atoms2);
        if (matchndxfile)
        {
            fp = ffopen(matchndxfile, "w");
            fprintf(fp, "; Matching atoms between %s from %s and %s from %s\n",
                    groupnames1, conf1file, groupnames2, conf2file);
            fprintf(fp, "[ Match_%s_%s ]\n", conf1file, groupnames1);
            for (i = 0; i < isize1; i++)
            {
                fprintf(fp, "%4u%s", index1[i]+1, (i%15 == 14 || i == isize1-1) ? "\n" : " ");
            }
            fprintf(fp, "[ Match_%s_%s ]\n", conf2file, groupnames2);
            for (i = 0; i < isize2; i++)
            {
                fprintf(fp, "%4u%s", index2[i]+1, (i%15 == 14 || i == isize2-1) ? "\n" : " ");
            }
        }
    }

    /* check isizes, must be equal */
    if (isize2 != isize1)
    {
        gmx_fatal(FARGS, "You selected groups with differen number of atoms.\n");
    }

    for (i = 0; i < isize1; i++)
    {
        name1 = *atoms1->atomname[index1[i]];
        name2 = *atoms2->atomname[index2[i]];
        if (strcmp(name1, name2))
        {
            if (warn < 20)
            {
                fprintf(stderr,
                        "Warning: atomnames at index %d don't match: %u %s, %u %s\n",
                        i+1, index1[i]+1, name1, index2[i]+1, name2);
            }
            warn++;
        }
        if (!bMW)
        {
            atoms1->atom[index1[i]].m = 1;
            atoms2->atom[index2[i]].m = 1;
        }
    }
    if (warn)
    {
        fprintf(stderr, "%d atomname%s did not match\n", warn, (warn == 1) ? "" : "s");
    }

    if (bFit)
    {
        /* calculate and remove center of mass of structures */
        calc_rm_cm(isize1, index1, atoms1, x1, xcm1);
        calc_rm_cm(isize2, index2, atoms2, x2, xcm2);

        snew(w_rls, atoms2->nr);
        snew(fit_x, atoms2->nr);
        for (at = 0; (at < isize1); at++)
        {
            w_rls[index2[at]] = atoms1->atom[index1[at]].m;
            copy_rvec(x1[index1[at]], fit_x[index2[at]]);
        }

        /* do the least squares fit to the reference structure */
        do_fit(atoms2->nr, w_rls, fit_x, x2);

        sfree(fit_x);
        sfree(w_rls);
        w_rls = NULL;
    }
    else
    {
        clear_rvec(xcm1);
        clear_rvec(xcm2);
        w_rls = NULL;
    }

    /* calculate the rms deviation */
    rms     = 0;
    totmass = 0;
    maxmsd  = -1e18;
    minmsd  =  1e18;
    snew(msds, isize1);
    for (at = 0; at < isize1; at++)
    {
        mass = atoms1->atom[index1[at]].m;
        for (m = 0; m < DIM; m++)
        {
            msd       = sqr(x1[index1[at]][m] - x2[index2[at]][m]);
            rms      += msd*mass;
            msds[at] += msd;
        }
        maxmsd   = max(maxmsd, msds[at]);
        minmsd   = min(minmsd, msds[at]);
        totmass += mass;
    }
    rms = sqrt(rms/totmass);

    printf("Root mean square deviation after lsq fit = %g nm\n", rms);
    if (bBfac)
    {
        printf("Atomic MSD's range from %g to %g nm^2\n", minmsd, maxmsd);
    }

    if (bFit)
    {
        /* reset coordinates of reference and fitted structure */
        for (i = 0; i < atoms1->nr; i++)
        {
            for (m = 0; m < DIM; m++)
            {
                x1[i][m] += xcm1[m];
            }
        }
        for (i = 0; i < atoms2->nr; i++)
        {
            for (m = 0; m < DIM; m++)
            {
                x2[i][m] += xcm1[m];
            }
        }
    }

    outfile = ftp2fn(efSTO, NFILE, fnm);
    switch (fn2ftp(outfile))
    {
        case efPDB:
        case efBRK:
        case efENT:
            if (bBfac || bLabel)
            {
                srenew(atoms1->pdbinfo, atoms1->nr);
                srenew(atoms1->atom, atoms1->nr); /* Why renew atom? */

                /* Avoid segfaults when writing the pdb-file */
                for (i = 0; i < atoms1->nr; i++)
                {
                    atoms1->pdbinfo[i].type         = eptAtom;
                    atoms1->pdbinfo[i].occup        = 1.00;
                    atoms1->pdbinfo[i].bAnisotropic = FALSE;
                    if (bBfac)
                    {
                        atoms1->pdbinfo[i].bfac = 0;
                    }
                    if (bLabel)
                    {
                        atoms1->resinfo[atoms1->atom[i].resind].chainid = 'A';
                    }
                }

                for (i = 0; i < isize1; i++)
                {
                    /* atoms1->pdbinfo[index1[i]].type = eptAtom; */
/*  atoms1->pdbinfo[index1[i]].bAnisotropic = FALSE; */
                    if (bBfac)
                    {
                        atoms1->pdbinfo[index1[i]].bfac = (800*M_PI*M_PI/3.0)*msds[i];
                    }
/*  if (bLabel) */
/*    atoms1->resinfo[atoms1->atom[index1[i]].resind].chain = 'A'; */
                }
                srenew(atoms2->pdbinfo, atoms2->nr);
                srenew(atoms2->atom, atoms2->nr); /* Why renew atom? */

                for (i = 0; i < atoms2->nr; i++)
                {
                    atoms2->pdbinfo[i].type         = eptAtom;
                    atoms2->pdbinfo[i].occup        = 1.00;
                    atoms2->pdbinfo[i].bAnisotropic = FALSE;
                    if (bBfac)
                    {
                        atoms2->pdbinfo[i].bfac = 0;
                    }
                    if (bLabel)
                    {
                        atoms2->resinfo[atoms1->atom[i].resind].chainid = 'B';
                    }
                }

                for (i = 0; i < isize2; i++)
                {
                    /* atoms2->pdbinfo[index2[i]].type = eptAtom; */
/*  atoms2->pdbinfo[index2[i]].bAnisotropic = FALSE; */
                    if (bBfac)
                    {
                        atoms2->pdbinfo[index2[i]].bfac = (800*M_PI*M_PI/3.0)*msds[i];
                    }
/*  if (bLabel) */
/*    atoms2->resinfo[atoms2->atom[index2[i]].resind].chain = 'B'; */
                }
            }
            fp = ffopen(outfile, "w");
            if (!bOne)
            {
                write_pdbfile(fp, title1, atoms1, x1, ePBC1, box1, ' ', 1, NULL, TRUE);
            }
            write_pdbfile(fp, title2, atoms2, x2, ePBC2, box2, ' ', bOne ? -1 : 2, NULL, TRUE);
            ffclose(fp);
            break;
        case efGRO:
            if (bBfac)
            {
                fprintf(stderr, "WARNING: cannot write B-factor values to gro file\n");
            }
            fp = ffopen(outfile, "w");
            if (!bOne)
            {
                write_hconf_p(fp, title1, atoms1, 3, x1, v1, box1);
            }
            write_hconf_p(fp, title2, atoms2, 3, x2, v2, box2);
            ffclose(fp);
            break;
        default:
            if (bBfac)
            {
                fprintf(stderr, "WARNING: cannot write B-factor values to %s file\n",
                        ftp2ext(fn2ftp(outfile)));
            }
            if (!bOne)
            {
                fprintf(stderr,
                        "WARNING: cannot write the reference structure to %s file\n",
                        ftp2ext(fn2ftp(outfile)));
            }
            write_sto_conf(outfile, title2, atoms2, x2, v2, ePBC2, box2);
            break;
    }

    view_all(oenv, NFILE, fnm);

    thanx(stderr);

    return 0;
}