added Verlet scheme and NxN non-bonded functionality
[gromacs.git] / src / tools / gmx_rmsdist.c
blob5547be664b3612303563310a8f2692c6b4da281f
1 /*
2 *
3 * This source code is part of
4 *
5 * G R O M A C S
6 *
7 * GROningen MAchine for Chemical Simulations
8 *
9 * VERSION 3.2.0
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
32 * And Hey:
33 * Green Red Orange Magenta Azure Cyan Skyblue
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
39 #include <math.h>
40 #include <ctype.h>
42 #include "macros.h"
43 #include "smalloc.h"
44 #include "typedefs.h"
45 #include "names.h"
46 #include "copyrite.h"
47 #include "statutil.h"
48 #include "tpxio.h"
49 #include "string2.h"
50 #include "strdb.h"
51 #include "vec.h"
52 #include "macros.h"
53 #include "index.h"
54 #include "pbc.h"
55 #include "xvgr.h"
56 #include "futil.h"
57 #include "matio.h"
58 #include "gmx_ana.h"
61 static void calc_dist(int nind,atom_id index[],rvec x[],int ePBC,matrix box,
62 real **d)
64 int i,j;
65 real *xi;
66 rvec dx;
67 real temp2;
68 t_pbc pbc;
70 set_pbc(&pbc,ePBC,box);
71 for(i=0; (i<nind-1); i++) {
72 xi=x[index[i]];
73 for(j=i+1; (j<nind); j++) {
74 pbc_dx(&pbc,xi,x[index[j]],dx);
75 temp2=norm2(dx);
76 d[i][j]=sqrt(temp2);
81 static void calc_dist_tot(int nind,atom_id index[],rvec x[],
82 int ePBC,matrix box,
83 real **d, real **dtot, real **dtot2,
84 gmx_bool bNMR, real **dtot1_3, real **dtot1_6)
86 int i,j;
87 real *xi;
88 real temp, temp2, temp1_3;
89 rvec dx;
90 t_pbc pbc;
92 set_pbc(&pbc,ePBC,box);
93 for(i=0; (i<nind-1); i++) {
94 xi=x[index[i]];
95 for(j=i+1; (j<nind); j++) {
96 pbc_dx(&pbc,xi,x[index[j]],dx);
97 temp2=norm2(dx);
98 temp =sqrt(temp2);
99 d[i][j]=temp;
100 dtot[i][j]+=temp;
101 dtot2[i][j]+=temp2;
102 if (bNMR) {
103 temp1_3 = 1.0/(temp*temp2);
104 dtot1_3[i][j] += temp1_3;
105 dtot1_6[i][j] += temp1_3*temp1_3;
111 static void calc_nmr(int nind, int nframes, real **dtot1_3, real **dtot1_6,
112 real *max1_3, real *max1_6)
114 int i,j;
115 real temp1_3,temp1_6;
117 for(i=0; (i<nind-1); i++) {
118 for(j=i+1; (j<nind); j++) {
119 temp1_3 = pow(dtot1_3[i][j]/nframes,-1.0/3.0);
120 temp1_6 = pow(dtot1_6[i][j]/nframes,-1.0/6.0);
121 if (temp1_3 > *max1_3) *max1_3 = temp1_3;
122 if (temp1_6 > *max1_6) *max1_6 = temp1_6;
123 dtot1_3[i][j] = temp1_3;
124 dtot1_6[i][j] = temp1_6;
125 dtot1_3[j][i] = temp1_3;
126 dtot1_6[j][i] = temp1_6;
131 static char Hnum[] = "123";
133 typedef struct {
134 int nr;
135 real r_3;
136 real r_6;
137 real i_3;
138 real i_6;
139 } t_noe;
141 typedef struct {
142 int anr;
143 int ianr;
144 int rnr;
145 char *aname;
146 char *rname;
147 } t_noe_gr;
149 typedef struct {
150 int rnr;
151 char *nname;
152 char *rname;
153 char *aname;
154 } t_equiv;
156 static int read_equiv(const char *eq_fn, t_equiv ***equivptr)
158 FILE *fp;
159 char line[STRLEN],resname[10],atomname[10],*lp;
160 int neq, na, n, resnr;
161 t_equiv **equiv;
163 fp = ffopen(eq_fn,"r");
164 neq=0;
165 equiv=NULL;
166 while(get_a_line(fp,line,STRLEN)) {
167 lp=line;
168 /* this is not efficient, but I'm lazy */
169 srenew(equiv,neq+1);
170 equiv[neq]=NULL;
171 na=0;
172 if (sscanf(lp,"%s %n",atomname,&n)==1) {
173 lp+=n;
174 snew(equiv[neq], 1);
175 equiv[neq][0].nname=strdup(atomname);
176 while (sscanf(lp,"%d %s %s %n",&resnr,resname,atomname,&n)==3) {
177 /* this is not efficient, but I'm lazy (again) */
178 srenew(equiv[neq], na+1);
179 equiv[neq][na].rnr=resnr-1;
180 equiv[neq][na].rname=strdup(resname);
181 equiv[neq][na].aname=strdup(atomname);
182 if (na>0) equiv[neq][na].nname=NULL;
183 na++;
184 lp+=n;
187 /* make empty element as flag for end of array */
188 srenew(equiv[neq], na+1);
189 equiv[neq][na].rnr=NOTSET;
190 equiv[neq][na].rname=NULL;
191 equiv[neq][na].aname=NULL;
193 /* next */
194 neq++;
196 ffclose(fp);
198 *equivptr=equiv;
200 return neq;
203 static void dump_equiv(FILE *out, int neq, t_equiv **equiv)
205 int i,j;
207 fprintf(out,"Dumping equivalent list\n");
208 for (i=0; i<neq; i++) {
209 fprintf(out,"%s",equiv[i][0].nname);
210 for(j=0; equiv[i][j].rnr!=NOTSET; j++)
211 fprintf(out," %d %s %s",
212 equiv[i][j].rnr,equiv[i][j].rname,equiv[i][j].aname);
213 fprintf(out,"\n");
217 static gmx_bool is_equiv(int neq, t_equiv **equiv, char **nname,
218 int rnr1, char *rname1, char *aname1,
219 int rnr2, char *rname2, char *aname2)
221 int i,j;
222 gmx_bool bFound;
224 bFound=FALSE;
225 /* we can terminate each loop when bFound is true! */
226 for (i=0; i<neq && !bFound; i++) {
227 /* find first atom */
228 for(j=0; equiv[i][j].rnr!=NOTSET && !bFound; j++)
229 bFound = ( equiv[i][j].rnr==rnr1 &&
230 strcmp(equiv[i][j].rname, rname1)==0 &&
231 strcmp(equiv[i][j].aname, aname1)==0 );
232 if (bFound) {
233 /* find second atom */
234 bFound=FALSE;
235 for(j=0; equiv[i][j].rnr!=NOTSET && !bFound; j++)
236 bFound = ( equiv[i][j].rnr==rnr2 &&
237 strcmp(equiv[i][j].rname, rname2)==0 &&
238 strcmp(equiv[i][j].aname, aname2)==0 );
241 if (bFound)
242 *nname = strdup(equiv[i-1][0].nname);
244 return bFound;
247 static int analyze_noe_equivalent(const char *eq_fn,
248 t_atoms *atoms, int isize, atom_id *index,
249 gmx_bool bSumH,
250 atom_id *noe_index, t_noe_gr *noe_gr)
252 FILE *fp;
253 int i, j, anmil, anmjl, rnri, rnrj, gi, groupnr, neq;
254 char *anmi, *anmj, **nnm;
255 gmx_bool bMatch,bEquiv;
256 t_equiv **equiv;
258 snew(nnm,isize);
259 if (bSumH) {
260 if (eq_fn) {
261 neq=read_equiv(eq_fn,&equiv);
262 if (debug) dump_equiv(debug,neq,equiv);
263 } else {
264 neq=0;
265 equiv=NULL;
268 groupnr=0;
269 for(i=0; i<isize; i++) {
270 if (equiv && i<isize-1) {
271 /* check explicit list of equivalent atoms */
272 do {
273 j=i+1;
274 rnri=atoms->atom[index[i]].resind;
275 rnrj=atoms->atom[index[j]].resind;
276 bEquiv =
277 is_equiv(neq, equiv, &nnm[i],
278 rnri,*atoms->resinfo[rnri].name,*atoms->atomname[index[i]],
279 rnrj,*atoms->resinfo[rnrj].name,*atoms->atomname[index[j]]);
280 if(nnm[i] && bEquiv)
281 nnm[j]=strdup(nnm[i]);
282 if (bEquiv) {
283 /* set index for matching atom */
284 noe_index[j]=groupnr;
285 /* skip matching atom */
286 i=j;
288 } while ( bEquiv && i<isize-1 );
289 } else
290 bEquiv=FALSE;
291 if (!bEquiv) {
292 /* look for triplets of consecutive atoms with name XX?,
293 X are any number of letters or digits and ? goes from 1 to 3
294 This is supposed to cover all CH3 groups and the like */
295 anmi = *atoms->atomname[index[i]];
296 anmil = strlen(anmi);
297 bMatch = i<isize-3 && anmi[anmil-1]=='1';
298 if (bMatch)
299 for(j=1; j<3; j++) {
300 anmj = *atoms->atomname[index[i+j]];
301 anmjl = strlen(anmj);
302 bMatch = bMatch && ( anmil==anmjl && anmj[anmjl-1]==Hnum[j] &&
303 strncmp(anmi, anmj, anmil-1)==0 );
305 /* set index for this atom */
306 noe_index[i]=groupnr;
307 if (bMatch) {
308 /* set index for next two matching atoms */
309 for(j=1; j<3; j++)
310 noe_index[i+j]=groupnr;
311 /* skip matching atoms */
312 i+=2;
315 groupnr++;
317 } else {
318 /* make index without looking for equivalent atoms */
319 for(i=0; i<isize; i++)
320 noe_index[i]=i;
321 groupnr=isize;
323 noe_index[isize]=groupnr;
325 if (debug)
326 /* dump new names */
327 for(i=0; i<isize; i++) {
328 rnri=atoms->atom[index[i]].resind;
329 fprintf(debug,"%s %s %d -> %s\n",*atoms->atomname[index[i]],
330 *atoms->resinfo[rnri].name,rnri,nnm[i]?nnm[i]:"");
333 for(i=0; i<isize; i++) {
334 gi=noe_index[i];
335 if (!noe_gr[gi].aname) {
336 noe_gr[gi].ianr=i;
337 noe_gr[gi].anr=index[i];
338 if (nnm[i])
339 noe_gr[gi].aname=strdup(nnm[i]);
340 else {
341 noe_gr[gi].aname=strdup(*atoms->atomname[index[i]]);
342 if ( noe_index[i]==noe_index[i+1] )
343 noe_gr[gi].aname[strlen(noe_gr[gi].aname)-1]='*';
345 noe_gr[gi].rnr=atoms->atom[index[i]].resind;
346 noe_gr[gi].rname=strdup(*atoms->resinfo[noe_gr[gi].rnr].name);
347 /* dump group definitions */
348 if (debug) fprintf(debug,"%d %d %d %d %s %s %d\n",i,gi,
349 noe_gr[gi].ianr,noe_gr[gi].anr,noe_gr[gi].aname,
350 noe_gr[gi].rname,noe_gr[gi].rnr);
353 for(i=0; i<isize; i++)
354 sfree(nnm[i]);
355 sfree(nnm);
357 return groupnr;
360 /* #define NSCALE 3 */
361 /* static char *noe_scale[NSCALE+1] = { */
362 /* "strong", "medium", "weak", "none" */
363 /* }; */
364 #define NSCALE 6
366 static char *noe2scale(real r3, real r6, real rmax)
368 int i,s3, s6;
369 static char buf[NSCALE+1];
371 /* r goes from 0 to rmax
372 NSCALE*r/rmax goes from 0 to NSCALE
373 NSCALE - NSCALE*r/rmax goes from NSCALE to 0 */
374 s3 = NSCALE - min(NSCALE, (int)(NSCALE*r3/rmax));
375 s6 = NSCALE - min(NSCALE, (int)(NSCALE*r6/rmax));
377 for(i=0; i<s3; i++)
378 buf[i]='=';
379 for( ; i<s6; i++)
380 buf[i]='-';
381 buf[i]='\0';
383 return buf;
386 static void calc_noe(int isize, atom_id *noe_index,
387 real **dtot1_3, real **dtot1_6, int gnr, t_noe **noe)
389 int i, j, gi, gj;
391 /* make half matrix of noe-group distances from atom distances */
392 for(i=0; i<isize; i++) {
393 gi=noe_index[i];
394 for(j=i; j<isize; j++) {
395 gj=noe_index[j];
396 noe[gi][gj].nr++;
397 noe[gi][gj].i_3+=pow(dtot1_3[i][j],-3);
398 noe[gi][gj].i_6+=pow(dtot1_6[i][j],-6);
402 /* make averages */
403 for(i=0; i<gnr; i++)
404 for(j=i+1; j<gnr; j++) {
405 noe[i][j].r_3 = pow(noe[i][j].i_3/noe[i][j].nr,-1.0/3.0);
406 noe[i][j].r_6 = pow(noe[i][j].i_6/noe[i][j].nr,-1.0/6.0);
407 noe[j][i] = noe[i][j];
411 static void write_noe(FILE *fp,int gnr,t_noe **noe,t_noe_gr *noe_gr,real rmax)
413 int i,j;
414 real r3, r6, min3, min6;
415 char buf[10],b3[10],b6[10];
416 t_noe_gr gri, grj;
418 min3 = min6 = 1e6;
419 fprintf(fp,
420 ";%4s %3s %4s %4s%3s %4s %4s %4s %4s%3s %5s %5s %8s %2s %2s %s\n",
421 "ianr","anr","anm","rnm","rnr","ianr","anr","anm","rnm","rnr",
422 "1/r^3","1/r^6","intnsty","Dr","Da","scale");
423 for(i=0; i<gnr; i++) {
424 gri=noe_gr[i];
425 for(j=i+1; j<gnr; j++) {
426 grj=noe_gr[j];
427 r3 = noe[i][j].r_3;
428 r6 = noe[i][j].r_6;
429 min3 = min(r3,min3);
430 min6 = min(r6,min6);
431 if ( r3 < rmax || r6 < rmax ) {
432 if (grj.rnr == gri.rnr)
433 sprintf(buf,"%2d", grj.anr-gri.anr);
434 else
435 buf[0]='\0';
436 if ( r3 < rmax )
437 sprintf(b3,"%-5.3f",r3);
438 else
439 strcpy(b3,"-");
440 if ( r6 < rmax )
441 sprintf(b6,"%-5.3f",r6);
442 else
443 strcpy(b6,"-");
444 fprintf(fp,
445 "%4d %4d %4s %4s%3d %4d %4d %4s %4s%3d %5s %5s %8d %2d %2s %s\n",
446 gri.ianr+1, gri.anr+1, gri.aname, gri.rname, gri.rnr+1,
447 grj.ianr+1, grj.anr+1, grj.aname, grj.rname, grj.rnr+1,
448 b3, b6, (int)(noe[i][j].i_6+0.5), grj.rnr-gri.rnr, buf,
449 noe2scale(r3, r6, rmax));
453 #define MINI ((i==3)?min3:min6)
454 for(i=3; i<=6; i+=3)
455 if ( MINI > rmax )
456 fprintf(stdout,"NOTE: no 1/r^%d averaged distances found below %g, "
457 "smallest was %g\n", i, rmax, MINI );
458 else
459 fprintf(stdout,"Smallest 1/r^%d averaged distance was %g\n", i, MINI );
460 #undef MINI
463 static void calc_rms(int nind, int nframes,
464 real **dtot, real **dtot2,
465 real **rmsmat, real *rmsmax,
466 real **rmscmat, real *rmscmax,
467 real **meanmat, real *meanmax)
469 int i,j;
470 real mean, mean2, rms, rmsc;
471 /* N.B. dtot and dtot2 contain the total distance and the total squared
472 * distance respectively, BUT they return RMS and the scaled RMS resp.
475 *rmsmax=-1000;
476 *rmscmax=-1000;
477 *meanmax=-1000;
479 for(i=0; (i<nind-1); i++) {
480 for(j=i+1; (j<nind); j++) {
481 mean =dtot[i][j]/nframes;
482 mean2=dtot2[i][j]/nframes;
483 rms=sqrt(max(0,mean2-mean*mean));
484 rmsc=rms/mean;
485 if (mean > *meanmax) *meanmax=mean;
486 if (rms > *rmsmax ) *rmsmax =rms;
487 if (rmsc > *rmscmax) *rmscmax=rmsc;
488 meanmat[i][j]=meanmat[j][i]=mean;
489 rmsmat[i][j] =rmsmat[j][i] =rms;
490 rmscmat[i][j]=rmscmat[j][i]=rmsc;
495 real rms_diff(int natom,real **d,real **d_r)
497 int i,j;
498 real r,r2;
500 r2=0.0;
501 for(i=0; (i<natom-1); i++)
502 for(j=i+1; (j<natom); j++) {
503 r=d[i][j]-d_r[i][j];
504 r2+=r*r;
506 r2/=(natom*(natom-1))/2;
508 return sqrt(r2);
511 int gmx_rmsdist (int argc,char *argv[])
513 const char *desc[] = {
514 "[TT]g_rmsdist[tt] computes the root mean square deviation of atom distances,",
515 "which has the advantage that no fit is needed like in standard RMS",
516 "deviation as computed by [TT]g_rms[tt].",
517 "The reference structure is taken from the structure file.",
518 "The RMSD at time t is calculated as the RMS",
519 "of the differences in distance between atom-pairs in the reference",
520 "structure and the structure at time t.[PAR]",
521 "[TT]g_rmsdist[tt] can also produce matrices of the rms distances, rms distances",
522 "scaled with the mean distance and the mean distances and matrices with",
523 "NMR averaged distances (1/r^3 and 1/r^6 averaging). Finally, lists",
524 "of atom pairs with 1/r^3 and 1/r^6 averaged distance below the",
525 "maximum distance ([TT]-max[tt], which will default to 0.6 in this case)",
526 "can be generated, by default averaging over equivalent hydrogens",
527 "(all triplets of hydrogens named *[123]). Additionally a list of",
528 "equivalent atoms can be supplied ([TT]-equiv[tt]), each line containing",
529 "a set of equivalent atoms specified as residue number and name and",
530 "atom name; e.g.:[PAR]",
531 "[TT]3 SER HB1 3 SER HB2[tt][PAR]",
532 "Residue and atom names must exactly match those in the structure",
533 "file, including case. Specifying non-sequential atoms is undefined."
537 int natom,i,j,teller,gi,gj;
538 real t;
540 t_topology top;
541 int ePBC;
542 t_atoms *atoms;
543 matrix box;
544 rvec *x;
545 FILE *fp;
547 t_trxstatus *status;
548 int isize,gnr=0;
549 atom_id *index, *noe_index;
550 char *grpname;
551 real **d_r,**d,**dtot,**dtot2,**mean,**rms,**rmsc,*resnr;
552 real **dtot1_3=NULL,**dtot1_6=NULL;
553 real rmsnow,meanmax,rmsmax,rmscmax;
554 real max1_3,max1_6;
555 t_noe_gr *noe_gr=NULL;
556 t_noe **noe=NULL;
557 t_rgb rlo,rhi;
558 char buf[255];
559 gmx_bool bRMS, bScale, bMean, bNOE, bNMR3, bNMR6, bNMR;
561 static int nlevels=40;
562 static real scalemax=-1.0;
563 static gmx_bool bSumH=TRUE;
564 static gmx_bool bPBC=TRUE;
565 output_env_t oenv;
567 t_pargs pa[] = {
568 { "-nlevels", FALSE, etINT, {&nlevels},
569 "Discretize RMS in this number of levels" },
570 { "-max", FALSE, etREAL, {&scalemax},
571 "Maximum level in matrices" },
572 { "-sumh", FALSE, etBOOL, {&bSumH},
573 "Average distance over equivalent hydrogens" },
574 { "-pbc", FALSE, etBOOL, {&bPBC},
575 "Use periodic boundary conditions when computing distances" }
577 t_filenm fnm[] = {
578 { efTRX, "-f", NULL, ffREAD },
579 { efTPS, NULL, NULL, ffREAD },
580 { efNDX, NULL, NULL, ffOPTRD },
581 { efDAT, "-equiv","equiv", ffOPTRD },
582 { efXVG, NULL, "distrmsd", ffWRITE },
583 { efXPM, "-rms", "rmsdist", ffOPTWR },
584 { efXPM, "-scl", "rmsscale", ffOPTWR },
585 { efXPM, "-mean","rmsmean", ffOPTWR },
586 { efXPM, "-nmr3","nmr3", ffOPTWR },
587 { efXPM, "-nmr6","nmr6", ffOPTWR },
588 { efDAT, "-noe", "noe", ffOPTWR },
590 #define NFILE asize(fnm)
592 CopyRight(stderr,argv[0]);
593 parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE ,
594 NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv);
596 bRMS = opt2bSet("-rms", NFILE,fnm);
597 bScale= opt2bSet("-scl", NFILE,fnm);
598 bMean = opt2bSet("-mean",NFILE,fnm);
599 bNOE = opt2bSet("-noe", NFILE,fnm);
600 bNMR3 = opt2bSet("-nmr3",NFILE,fnm);
601 bNMR6 = opt2bSet("-nmr6",NFILE,fnm);
602 bNMR = bNMR3 || bNMR6 || bNOE;
604 max1_3 = 0;
605 max1_6 = 0;
607 /* check input */
608 if (bNOE && scalemax < 0) {
609 scalemax=0.6;
610 fprintf(stderr,"WARNING: using -noe without -max "
611 "makes no sense, setting -max to %g\n\n",scalemax);
614 /* get topology and index */
615 read_tps_conf(ftp2fn(efTPS,NFILE,fnm),buf,&top,&ePBC,&x,NULL,box,FALSE);
617 if (!bPBC)
618 ePBC = epbcNONE;
619 atoms=&(top.atoms);
621 get_index(atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&isize,&index,&grpname);
623 /* initialize arrays */
624 snew(d,isize);
625 snew(dtot,isize);
626 snew(dtot2,isize);
627 if (bNMR) {
628 snew(dtot1_3,isize);
629 snew(dtot1_6,isize);
631 snew(mean,isize);
632 snew(rms,isize);
633 snew(rmsc,isize);
634 snew(d_r,isize);
635 snew(resnr,isize);
636 for(i=0; (i<isize); i++) {
637 snew(d[i],isize);
638 snew(dtot[i],isize);
639 snew(dtot2[i],isize);
640 if (bNMR) {
641 snew(dtot1_3[i],isize);
642 snew(dtot1_6[i],isize);
644 snew(mean[i],isize);
645 snew(rms[i],isize);
646 snew(rmsc[i],isize);
647 snew(d_r[i],isize);
648 resnr[i]=i+1;
651 /*set box type*/
652 calc_dist(isize,index,x,ePBC,box,d_r);
653 sfree(x);
655 /*open output files*/
656 fp=xvgropen(ftp2fn(efXVG,NFILE,fnm),"RMS Deviation","Time (ps)","RMSD (nm)",
657 oenv);
658 if (output_env_get_print_xvgr_codes(oenv))
659 fprintf(fp,"@ subtitle \"of distances between %s atoms\"\n",grpname);
661 /*do a first step*/
662 natom=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
664 do {
665 calc_dist_tot(isize,index,x,ePBC,box,d,dtot,dtot2,bNMR,dtot1_3,dtot1_6);
667 rmsnow=rms_diff(isize,d,d_r);
668 fprintf(fp,"%g %g\n",t,rmsnow);
669 } while (read_next_x(oenv,status,&t,natom,x,box));
670 fprintf(stderr, "\n");
672 ffclose(fp);
674 teller = nframes_read(status);
676 close_trj(status);
678 calc_rms(isize,teller,dtot,dtot2,mean,&meanmax,rms,&rmsmax,rmsc,&rmscmax);
679 fprintf(stderr,"rmsmax = %g, rmscmax = %g\n",rmsmax,rmscmax);
681 if (bNMR)
683 calc_nmr(isize,teller,dtot1_3,dtot1_6,&max1_3,&max1_6);
686 if (scalemax > -1.0) {
687 rmsmax=scalemax;
688 rmscmax=scalemax;
689 meanmax=scalemax;
690 max1_3=scalemax;
691 max1_6=scalemax;
694 if (bNOE) {
695 /* make list of noe atom groups */
696 snew(noe_index, isize+1);
697 snew(noe_gr, isize);
698 gnr=analyze_noe_equivalent(opt2fn_null("-equiv",NFILE,fnm),
699 atoms, isize, index, bSumH, noe_index, noe_gr);
700 fprintf(stdout, "Found %d non-equivalent atom-groups in %d atoms\n",
701 gnr, isize);
702 /* make half matrix of of noe-group distances from atom distances */
703 snew(noe,gnr);
704 for(i=0; i<gnr; i++)
705 snew(noe[i],gnr);
706 calc_noe(isize, noe_index, dtot1_3, dtot1_6, gnr, noe);
709 rlo.r=1.0, rlo.g=1.0, rlo.b=1.0;
710 rhi.r=0.0, rhi.g=0.0, rhi.b=0.0;
712 if ( bRMS )
713 write_xpm(opt2FILE("-rms",NFILE,fnm,"w"),0,
714 "RMS of distance","RMS (nm)","Atom Index","Atom Index",
715 isize,isize,resnr,resnr,rms,0.0,rmsmax,rlo,rhi,&nlevels);
717 if ( bScale )
718 write_xpm(opt2FILE("-scl",NFILE,fnm,"w"),0,
719 "Relative RMS","RMS","Atom Index","Atom Index",
720 isize,isize,resnr,resnr,rmsc,0.0,rmscmax,rlo,rhi,&nlevels);
722 if ( bMean )
723 write_xpm(opt2FILE("-mean",NFILE,fnm,"w"),0,
724 "Mean Distance","Distance (nm)","Atom Index","Atom Index",
725 isize,isize,resnr,resnr,mean,0.0,meanmax,rlo,rhi,&nlevels);
727 if (bNMR3)
728 write_xpm(opt2FILE("-nmr3",NFILE,fnm,"w"),0,"1/r^3 averaged distances",
729 "Distance (nm)","Atom Index","Atom Index",
730 isize,isize,resnr,resnr,dtot1_3,0.0,max1_3,rlo,rhi,&nlevels);
731 if (bNMR6)
732 write_xpm(opt2FILE("-nmr6",NFILE,fnm,"w"),0,"1/r^6 averaged distances",
733 "Distance (nm)","Atom Index","Atom Index",
734 isize,isize,resnr,resnr,dtot1_6,0.0,max1_6,rlo,rhi,&nlevels);
736 if (bNOE)
737 write_noe(opt2FILE("-noe",NFILE,fnm,"w"), gnr, noe, noe_gr, scalemax);
739 do_view(oenv,ftp2fn(efXVG,NFILE,fnm),NULL);
741 thanx(stderr);
742 return 0;