3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
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
33 * Green Red Orange Magenta Azure Cyan Skyblue
49 #include "gmx_fatal.h"
61 static void norm_princ(t_atoms
*atoms
, int isize
, atom_id
*index
, int natoms
,
67 /* equalize principal components: */
68 /* orient principal axes, get principal components */
69 orient_princ(atoms
, isize
, index
, natoms
, x
, NULL
, princ
);
71 /* calc our own principal components */
73 for (m
= 0; m
< DIM
; m
++)
75 for (i
= 0; i
< isize
; i
++)
76 vec
[m
] += sqr(x
[index
[i
]][m
]);
77 vec
[m
] = sqrt(vec
[m
] / isize
);
78 /* calculate scaling constants */
79 vec
[m
] = 1 / (sqrt(3) * vec
[m
]);
82 /* scale coordinates */
83 for (i
= 0; i
< natoms
; i
++)
85 for (m
= 0; m
< DIM
; m
++)
92 int gmx_rms(int argc
, char *argv
[])
97 "g_rms compares two structures by computing the root mean square",
98 "deviation (RMSD), the size-independent 'rho' similarity parameter",
99 "(rho) or the scaled rho (rhosc), ",
100 "see Maiorov & Crippen, PROTEINS [BB]22[bb], 273 (1995).",
101 "This is selected by [TT]-what[tt].[PAR]"
103 "Each structure from a trajectory ([TT]-f[tt]) is compared to a",
104 "reference structure. The reference structure",
105 "is taken from the structure file ([TT]-s[tt]).[PAR]",
107 "With option [TT]-mir[tt] also a comparison with the mirror image of",
108 "the reference structure is calculated.",
109 "This is useful as a reference for 'significant' values, see",
110 "Maiorov & Crippen, PROTEINS [BB]22[bb], 273 (1995).[PAR]",
112 "Option [TT]-prev[tt] produces the comparison with a previous frame",
113 "the specified number of frames ago.[PAR]",
115 "Option [TT]-m[tt] produces a matrix in [TT].xpm[tt] format of",
116 "comparison values of each structure in the trajectory with respect to",
117 "each other structure. This file can be visualized with for instance",
118 "[TT]xv[tt] and can be converted to postscript with [TT]xpm2ps[tt].[PAR]",
120 "Option [TT]-fit[tt] controls the least-squares fitting of",
121 "the structures on top of each other: complete fit (rotation and",
122 "translation), translation only, or no fitting at all.[PAR]",
124 "Option [TT]-mw[tt] controls whether mass weighting is done or not.",
125 "If you select the option (default) and ",
126 "supply a valid tpr file masses will be taken from there, ",
127 "otherwise the masses will be deduced from the atommass.dat file in",
128 "the GROMACS library directory. This is fine for proteins but not",
129 "necessarily for other molecules. A default mass of 12.011 amu (Carbon)",
130 "is assigned to unknown atoms. You can check whether this happend by",
131 "turning on the [TT]-debug[tt] flag and inspecting the log file.[PAR]",
133 "With [TT]-f2[tt], the 'other structures' are taken from a second",
134 "trajectory, this generates a comparison matrix of one trajectory",
135 "versus the other.[PAR]",
137 "Option [TT]-bin[tt] does a binary dump of the comparison matrix.[PAR]",
139 "Option [TT]-bm[tt] produces a matrix of average bond angle deviations",
140 "analogously to the [TT]-m[tt] option. Only bonds between atoms in the",
141 "comparison group are considered." };
142 static bool bPBC
= TRUE
, bFitAll
= TRUE
, bSplit
= FALSE
;
143 static bool bDeltaLog
= FALSE
;
144 static int prev
= 0, freq
= 1, freq2
= 1, nlevels
= 80, avl
= 0;
145 static real rmsd_user_max
= -1, rmsd_user_min
= -1, bond_user_max
= -1,
146 bond_user_min
= -1, delta_maxy
= 0.0;
147 /* strings and things for selecting difference method */
150 ewSel
, ewRMSD
, ewRho
, ewRhoSc
, ewNR
153 const char *what
[ewNR
+ 1] =
154 { NULL
, "rmsd", "rho", "rhosc", NULL
};
155 const char *whatname
[ewNR
] =
156 { NULL
, "RMSD", "Rho", "Rho sc" };
157 const char *whatlabel
[ewNR
] =
158 { NULL
, "RMSD (nm)", "Rho", "Rho sc" };
159 const char *whatxvgname
[ewNR
] =
160 { NULL
, "RMSD", "\\8r\\4", "\\8r\\4\\ssc\\N" };
161 const char *whatxvglabel
[ewNR
] =
162 { NULL
, "RMSD (nm)", "\\8r\\4", "\\8r\\4\\ssc\\N" };
163 /* strings and things for fitting methods */
166 efSel
, efFit
, efReset
, efNone
, efNR
169 const char *fit
[efNR
+ 1] =
170 { NULL
, "rot+trans", "translation", "none", NULL
};
171 const char *fitgraphlabel
[efNR
+ 1] =
172 { NULL
, "lsq fit", "translational fit", "no fit" };
174 static bool bMassWeighted
= TRUE
;
177 { "-what", FALSE
, etENUM
,
178 { what
}, "Structural difference measure" },
179 { "-pbc", FALSE
, etBOOL
,
180 { &bPBC
}, "PBC check" },
181 { "-fit", FALSE
, etENUM
,
182 { fit
}, "Fit to reference structure" },
183 { "-prev", FALSE
, etINT
,
184 { &prev
}, "Compare with previous frame" },
185 { "-split", FALSE
, etBOOL
,
186 { &bSplit
}, "Split graph where time is zero" },
187 { "-fitall", FALSE
, etBOOL
,
188 { &bFitAll
}, "HIDDENFit all pairs of structures in matrix" },
189 { "-skip", FALSE
, etINT
,
190 { &freq
}, "Only write every nr-th frame to matrix" },
191 { "-skip2", FALSE
, etINT
,
192 { &freq2
}, "Only write every nr-th frame to matrix" },
193 { "-max", FALSE
, etREAL
,
194 { &rmsd_user_max
}, "Maximum level in comparison matrix" },
195 { "-min", FALSE
, etREAL
,
196 { &rmsd_user_min
}, "Minimum level in comparison matrix" },
197 { "-bmax", FALSE
, etREAL
,
198 { &bond_user_max
}, "Maximum level in bond angle matrix" },
199 { "-bmin", FALSE
, etREAL
,
200 { &bond_user_min
}, "Minimum level in bond angle matrix" },
201 { "-mw", FALSE
, etBOOL
,
202 { &bMassWeighted
}, "Use mass weighting for superposition" },
203 { "-nlevels", FALSE
, etINT
,
204 { &nlevels
}, "Number of levels in the matrices" },
205 { "-ng", FALSE
, etINT
,
206 { &nrms
}, "Number of groups to compute RMS between" },
207 { "-dlog", FALSE
, etBOOL
,
209 "HIDDENUse a log x-axis in the delta t matrix" },
210 { "-dmax", FALSE
, etREAL
,
211 { &delta_maxy
}, "HIDDENMaximum level in delta matrix" },
212 { "-aver", FALSE
, etINT
,
214 "HIDDENAverage over this distance in the RMSD matrix" } };
216 int i
, j
, k
, m
, teller
, teller2
, tel_mat
, tel_mat2
;
218 int maxframe
= NFRAME
, maxframe2
= NFRAME
;
219 real t
, *w_rls
, *w_rms
, *w_rls_m
= NULL
, *w_rms_m
= NULL
;
220 bool bNorm
, bAv
, bFreq2
, bFile2
, bMat
, bBond
, bDelta
, bMirror
, bMass
;
224 t_iatom
*iatom
= NULL
;
227 rvec
*x
, *xp
, *xm
= NULL
, **mat_x
= NULL
, **mat_x2
, *mat_x2_j
= NULL
, vec1
,
230 char buf
[256], buf2
[256];
233 real rlstot
= 0, **rls
, **rlsm
= NULL
, *time
, *time2
, *rlsnorm
= NULL
,
234 **rmsd_mat
= NULL
, **bond_mat
= NULL
, *axis
, *axis2
, *del_xaxis
,
235 *del_yaxis
, rmsd_max
, rmsd_min
, rmsd_avg
, bond_max
, bond_min
, ang
;
236 real
**rmsdav_mat
= NULL
, av_tot
, weight
, weight_tot
;
237 real
**delta
= NULL
, delta_max
, delta_scalex
= 0, delta_scaley
= 0,
239 int delta_xsize
= 0, del_lev
= 100, mx
, my
, abs_my
;
240 bool bA1
, bA2
, bPrev
, bTop
, *bInMat
= NULL
;
241 int ifit
, *irms
, ibond
= 0, *ind_bond1
= NULL
, *ind_bond2
= NULL
, n_ind_m
=
243 atom_id
*ind_fit
, **ind_rms
, *ind_m
= NULL
, *rev_ind_m
= NULL
, *ind_rms_m
=
245 char *gn_fit
, **gn_rms
;
250 { efTPS
, NULL
, NULL
, ffREAD
},
251 { efTRX
, "-f", NULL
, ffREAD
},
252 { efTRX
, "-f2", NULL
, ffOPTRD
},
253 { efNDX
, NULL
, NULL
, ffOPTRD
},
254 { efXVG
, NULL
, "rmsd", ffWRITE
},
255 { efXVG
, "-mir", "rmsdmir", ffOPTWR
},
256 { efXVG
, "-a", "avgrp", ffOPTWR
},
257 { efXVG
, "-dist", "rmsd-dist", ffOPTWR
},
258 { efXPM
, "-m", "rmsd", ffOPTWR
},
259 { efDAT
, "-bin", "rmsd", ffOPTWR
},
260 { efXPM
, "-bm", "bond", ffOPTWR
} };
261 #define NFILE asize(fnm)
263 CopyRight(stderr
, argv
[0]);
264 parse_common_args(&argc
, argv
, PCA_CAN_TIME
| PCA_TIME_UNIT
| PCA_CAN_VIEW
265 | PCA_BE_NICE
, NFILE
, fnm
, asize(pa
), pa
, asize(desc
), desc
, 0, NULL
,
267 /* parse enumerated options: */
269 if (ewhat
== ewRho
|| ewhat
== ewRhoSc
)
270 please_cite(stdout
, "Maiorov95");
272 bFit
= efit
== efFit
;
273 bReset
= efit
== efReset
;
276 bReset
= TRUE
; /* for fit, reset *must* be set */
283 /* mark active cmdline options */
284 bMirror
= opt2bSet("-mir", NFILE
, fnm
); /* calc RMSD vs mirror of ref. */
285 bFile2
= opt2bSet("-f2", NFILE
, fnm
);
286 bMat
= opt2bSet("-m", NFILE
, fnm
);
287 bBond
= opt2bSet("-bm", NFILE
, fnm
);
288 bDelta
= (delta_maxy
> 0); /* calculate rmsd vs delta t matrix from *
289 * your RMSD matrix (hidden option */
290 bNorm
= opt2bSet("-a", NFILE
, fnm
);
291 bFreq2
= opt2parg_bSet("-skip2", asize(pa
), pa
);
294 fprintf(stderr
, "The number of frames to skip is <= 0. "
295 "Writing out all frames.\n\n");
302 else if (bFile2
&& freq2
<= 0)
305 "The number of frames to skip in second trajectory is <= 0.\n"
306 " Writing out all frames.\n\n");
315 fprintf(stderr
, "WARNING: option -skip also applies to -prev\n");
318 if (bFile2
&& !bMat
&& !bBond
)
322 "WARNING: second trajectory (-f2) useless when not calculating matrix (-m/-bm),\n"
323 " will not read from %s\n", opt2fn("-f2", NFILE
,
334 "WARNING: second trajectory (-f2) useless when making delta matrix,\n"
335 " will not read from %s\n", opt2fn("-f2",
341 bTop
= read_tps_conf(ftp2fn(efTPS
, NFILE
, fnm
), buf
, &top
, &ePBC
, &xp
,
343 snew(w_rls
,top
.atoms
.nr
);
344 snew(w_rms
,top
.atoms
.nr
);
349 "WARNING: Need a run input file for bond angle matrix,\n"
350 " will not calculate bond angle matrix.\n");
356 fprintf(stderr
, "Select group for %s fit\n", bFit
? "least squares"
358 get_index(&(top
.atoms
), ftp2fn_null(efNDX
, NFILE
, fnm
), 1, &ifit
,
366 if (bFit
&& ifit
< 3)
367 gmx_fatal(FARGS
,"Need >= 3 points to fit!\n" );
370 for(i
=0; i
<ifit
; i
++)
373 w_rls
[ind_fit
[i
]] = top
.atoms
.atom
[ind_fit
[i
]].m
;
375 w_rls
[ind_fit
[i
]] = 1;
376 bMass
= bMass
|| (top
.atoms
.atom
[ind_fit
[i
]].m
!= 0);
380 fprintf(stderr
,"All masses in the fit group are 0, using masses of 1\n");
381 for(i
=0; i
<ifit
; i
++)
383 w_rls
[ind_fit
[i
]] = 1;
395 fprintf(stderr
,"Select group%s for %s calculation\n",
396 (nrms
>1) ? "s" : "",whatname
[ewhat
]);
397 get_index(&(top
.atoms
),ftp2fn_null(efNDX
,NFILE
,fnm
),
398 nrms
,irms
,ind_rms
,gn_rms
);
402 snew(rlsnorm
,irms
[0]);
405 for(j
=0; j
<nrms
; j
++)
406 snew(rls
[j
],maxframe
);
410 for(j
=0; j
<nrms
; j
++)
411 snew(rlsm
[j
],maxframe
);
414 for(j
=0; j
<nrms
; j
++)
417 for(i
=0; i
<irms
[j
]; i
++)
420 w_rms
[ind_rms
[j
][i
]] = top
.atoms
.atom
[ind_rms
[j
][i
]].m
;
422 w_rms
[ind_rms
[j
][i
]] = 1.0;
423 bMass
= bMass
|| (top
.atoms
.atom
[ind_rms
[j
][i
]].m
!= 0);
426 fprintf(stderr
,"All masses in group %d are 0, using masses of 1\n",j
);
427 for(i
=0; i
<irms
[j
]; i
++)
428 w_rms
[ind_rms
[j
][i
]] = 1;
431 /* Prepare reference frame */
433 rm_pbc(&(top
.idef
),ePBC
,top
.atoms
.nr
,box
,xp
,xp
);
435 reset_x(ifit
,ind_fit
,top
.atoms
.nr
,NULL
,xp
,w_rls
);
437 /* generate reference structure mirror image: */
438 snew(xm
, top
.atoms
.nr
);
439 for(i
=0; i
<top
.atoms
.nr
; i
++) {
440 copy_rvec(xp
[i
],xm
[i
]);
441 xm
[i
][XX
] = -xm
[i
][XX
];
445 norm_princ(&top
.atoms
, ifit
, ind_fit
, top
.atoms
.nr
, xp
);
447 /* read first frame */
448 natoms
=read_first_x(oenv
,&status
,opt2fn("-f",NFILE
,fnm
),&t
,&x
,box
);
449 if (natoms
!= top
.atoms
.nr
)
451 "\nWARNING: topology has %d atoms, whereas trajectory has %d\n",
452 top
.atoms
.nr
,natoms
);
453 if (bMat
|| bBond
|| bPrev
) {
457 /* With -prev we use all atoms for simplicity */
460 /* Check which atoms we need (fit/rms) */
462 for(i
=0; i
<ifit
; i
++)
463 bInMat
[ind_fit
[i
]] = TRUE
;
465 for(i
=0; i
<irms
[0]; i
++)
466 if (!bInMat
[ind_rms
[0][i
]]) {
467 bInMat
[ind_rms
[0][i
]] = TRUE
;
471 /* Make an index of needed atoms */
473 snew(rev_ind_m
,natoms
);
475 for(i
=0; i
<natoms
; i
++)
476 if (bPrev
|| bInMat
[i
]) {
481 snew(w_rls_m
,n_ind_m
);
482 snew(ind_rms_m
,irms
[0]);
483 snew(w_rms_m
,n_ind_m
);
484 for(i
=0; i
<ifit
; i
++)
485 w_rls_m
[rev_ind_m
[ind_fit
[i
]]] = w_rls
[ind_fit
[i
]];
486 for(i
=0; i
<irms
[0]; i
++) {
487 ind_rms_m
[i
] = rev_ind_m
[ind_rms
[0][i
]];
488 w_rms_m
[ind_rms_m
[i
]] = w_rms
[ind_rms
[0][i
]];
495 for(k
=0; k
<F_NRE
; k
++)
496 if (IS_CHEMBOND(k
)) {
497 iatom
= top
.idef
.il
[k
].iatoms
;
498 ncons
+= top
.idef
.il
[k
].nr
/3;
500 fprintf(stderr
,"Found %d bonds in topology\n",ncons
);
501 snew(ind_bond1
,ncons
);
502 snew(ind_bond2
,ncons
);
504 for(k
=0; k
<F_NRE
; k
++)
505 if (IS_CHEMBOND(k
)) {
506 iatom
= top
.idef
.il
[k
].iatoms
;
507 ncons
= top
.idef
.il
[k
].nr
/3;
508 for (i
=0; i
<ncons
; i
++) {
511 for (j
=0; j
<irms
[0]; j
++) {
512 if (iatom
[3*i
+1] == ind_rms
[0][j
]) bA1
=TRUE
;
513 if (iatom
[3*i
+2] == ind_rms
[0][j
]) bA2
=TRUE
;
516 ind_bond1
[ibond
] = rev_ind_m
[iatom
[3*i
+1]];
517 ind_bond2
[ibond
] = rev_ind_m
[iatom
[3*i
+2]];
522 fprintf(stderr
,"Using %d bonds for bond angle matrix\n",ibond
);
524 gmx_fatal(FARGS
,"0 bonds found");
527 /* start looping over frames: */
532 rm_pbc(&(top
.idef
),ePBC
,natoms
,box
,x
,x
);
535 reset_x(ifit
,ind_fit
,natoms
,NULL
,x
,w_rls
);
537 norm_princ(&top
.atoms
, ifit
, ind_fit
, natoms
, x
);
540 /*do the least squares fit to original structure*/
541 do_fit(natoms
,w_rls
,xp
,x
);
543 if (teller
% freq
== 0) {
544 /* keep frame for matrix calculation */
545 if (bMat
|| bBond
|| bPrev
) {
546 if (tel_mat
>= NFRAME
)
547 srenew(mat_x
,tel_mat
+1);
548 snew(mat_x
[tel_mat
],n_ind_m
);
549 for (i
=0;i
<n_ind_m
;i
++)
550 copy_rvec(x
[ind_m
[i
]],mat_x
[tel_mat
][i
]);
555 /*calculate energy of root_least_squares*/
560 for (i
=0;i
<n_ind_m
;i
++)
561 copy_rvec(mat_x
[j
][i
],xp
[ind_m
[i
]]);
563 reset_x(ifit
,ind_fit
,natoms
,NULL
,xp
,w_rls
);
565 do_fit(natoms
,w_rls
,x
,xp
);
567 for(j
=0; (j
<nrms
); j
++)
569 calc_similar_ind(ewhat
!=ewRMSD
,irms
[j
],ind_rms
[j
],w_rms
,x
,xp
);
571 for(j
=0; (j
<irms
[0]); j
++)
573 calc_similar_ind(ewhat
!=ewRMSD
,1,&(ind_rms
[0][j
]),w_rms
,x
,xp
);
578 /*do the least squares fit to mirror of original structure*/
579 do_fit(natoms
,w_rls
,xm
,x
);
581 for(j
=0; j
<nrms
; j
++)
583 calc_similar_ind(ewhat
!=ewRMSD
,irms
[j
],ind_rms
[j
],w_rms
,x
,xm
);
585 time
[teller
]=output_env_conv_time(oenv
,t
);
588 if (teller
>= maxframe
) {
590 srenew(time
,maxframe
);
591 for(j
=0; (j
<nrms
); j
++)
592 srenew(rls
[j
],maxframe
);
594 for(j
=0; (j
<nrms
); j
++)
595 srenew(rlsm
[j
],maxframe
);
597 } while (read_next_x(oenv
,status
,&t
,natoms
,x
,box
));
601 snew(time2
,maxframe2
);
603 fprintf(stderr
,"\nWill read second trajectory file\n");
605 natoms2
=read_first_x(oenv
,&status
,opt2fn("-f2",NFILE
,fnm
),&t
,&x
,box
);
606 if ( natoms2
!= natoms
)
608 "Second trajectory (%d atoms) does not match the first one"
609 " (%d atoms)", natoms2
, natoms
);
614 rm_pbc(&(top
.idef
),ePBC
,natoms
,box
,x
,x
);
617 reset_x(ifit
,ind_fit
,natoms
,NULL
,x
,w_rls
);
619 norm_princ(&top
.atoms
, ifit
, ind_fit
, natoms
, x
);
622 /*do the least squares fit to original structure*/
623 do_fit(natoms
,w_rls
,xp
,x
);
625 if (teller2
% freq2
== 0) {
626 /* keep frame for matrix calculation */
628 if (tel_mat2
>= NFRAME
)
629 srenew(mat_x2
,tel_mat2
+1);
630 snew(mat_x2
[tel_mat2
],n_ind_m
);
631 for (i
=0;i
<n_ind_m
;i
++)
632 copy_rvec(x
[ind_m
[i
]],mat_x2
[tel_mat2
][i
]);
637 time2
[teller2
]=output_env_conv_time(oenv
,t
);
640 if (teller2
>= maxframe2
) {
642 srenew(time2
,maxframe2
);
644 } while (read_next_x(oenv
,status
,&t
,natoms
,x
,box
));
654 /* calculate RMS matrix */
655 fprintf(stderr
,"\n");
657 fprintf(stderr
,"Building %s matrix, %dx%d elements\n",
658 whatname
[ewhat
],tel_mat
,tel_mat2
);
659 snew(rmsd_mat
,tel_mat
);
662 fprintf(stderr
,"Building bond angle matrix, %dx%d elements\n",
664 snew(bond_mat
,tel_mat
);
667 snew(axis2
,tel_mat2
);
676 for(j
=0; j
<tel_mat2
; j
++)
677 axis2
[j
]=time2
[freq2
*j
];
680 delta_scalex
=8.0/log(2.0);
681 delta_xsize
=(int)(log(tel_mat
/2)*delta_scalex
+0.5)+1;
684 delta_xsize
=tel_mat
/2;
686 delta_scaley
=1.0/delta_maxy
;
687 snew(delta
,delta_xsize
);
688 for(j
=0; j
<delta_xsize
; j
++)
689 snew(delta
[j
],del_lev
+1);
691 snew(rmsdav_mat
,tel_mat
);
692 for(j
=0; j
<tel_mat
; j
++)
693 snew(rmsdav_mat
[j
],tel_mat
);
698 snew(mat_x2_j
,natoms
);
699 for(i
=0; i
<tel_mat
; i
++) {
700 axis
[i
]=time
[freq
*i
];
701 fprintf(stderr
,"\r element %5d; time %5.2f ",i
,axis
[i
]);
702 if (bMat
) snew(rmsd_mat
[i
],tel_mat2
);
703 if (bBond
) snew(bond_mat
[i
],tel_mat2
);
704 for(j
=0; j
<tel_mat2
; j
++) {
706 for (k
=0;k
<n_ind_m
;k
++)
707 copy_rvec(mat_x2
[j
][k
],mat_x2_j
[k
]);
708 do_fit(n_ind_m
,w_rls_m
,mat_x
[i
],mat_x2_j
);
712 if (bFile2
|| (i
<j
)) {
714 calc_similar_ind(ewhat
!=ewRMSD
,irms
[0],ind_rms_m
,
715 w_rms_m
,mat_x
[i
],mat_x2_j
);
716 if (rmsd_mat
[i
][j
] > rmsd_max
) rmsd_max
=rmsd_mat
[i
][j
];
717 if (rmsd_mat
[i
][j
] < rmsd_min
) rmsd_min
=rmsd_mat
[i
][j
];
718 rmsd_avg
+= rmsd_mat
[i
][j
];
720 rmsd_mat
[i
][j
]=rmsd_mat
[j
][i
];
723 if (bFile2
|| (i
<=j
)) {
725 for(m
=0;m
<ibond
;m
++) {
726 rvec_sub(mat_x
[i
][ind_bond1
[m
]],mat_x
[i
][ind_bond2
[m
]],vec1
);
727 rvec_sub(mat_x2_j
[ind_bond1
[m
]],mat_x2_j
[ind_bond2
[m
]],vec2
);
728 ang
+= acos(cos_angle(vec1
,vec2
));
730 bond_mat
[i
][j
]=ang
*180.0/(M_PI
*ibond
);
731 if (bond_mat
[i
][j
] > bond_max
) bond_max
=bond_mat
[i
][j
];
732 if (bond_mat
[i
][j
] < bond_min
) bond_min
=bond_mat
[i
][j
];
735 bond_mat
[i
][j
]=bond_mat
[j
][i
];
740 rmsd_avg
/= tel_mat
*tel_mat2
;
742 rmsd_avg
/= tel_mat
*(tel_mat
- 1)/2;
743 if (bMat
&& (avl
> 0)) {
747 for(j
=0; j
<tel_mat
-1; j
++) {
748 for(i
=j
+1; i
<tel_mat
; i
++) {
751 for (my
=-avl
; my
<=avl
; my
++) {
752 if ((j
+my
>=0) && (j
+my
<tel_mat
)) {
754 for (mx
=-avl
; mx
<=avl
; mx
++) {
755 if ((i
+mx
>=0) && (i
+mx
<tel_mat
)) {
756 weight
= (real
)(avl
+1-max(abs(mx
),abs_my
));
757 av_tot
+= weight
*rmsd_mat
[i
+mx
][j
+my
];
763 rmsdav_mat
[i
][j
] = av_tot
/weight_tot
;
764 rmsdav_mat
[j
][i
] = rmsdav_mat
[i
][j
];
765 if (rmsdav_mat
[i
][j
] > rmsd_max
) rmsd_max
=rmsdav_mat
[i
][j
];
772 fprintf(stderr
,"\n%s: Min %f, Max %f, Avg %f\n",
773 whatname
[ewhat
],rmsd_min
,rmsd_max
,rmsd_avg
);
774 rlo
.r
= 1; rlo
.g
= 1; rlo
.b
= 1;
775 rhi
.r
= 0; rhi
.g
= 0; rhi
.b
= 0;
776 if (rmsd_user_max
!= -1) rmsd_max
=rmsd_user_max
;
777 if (rmsd_user_min
!= -1) rmsd_min
=rmsd_user_min
;
778 if ((rmsd_user_max
!= -1) || (rmsd_user_min
!= -1))
779 fprintf(stderr
,"Min and Max value set to resp. %f and %f\n",
781 sprintf(buf
,"%s %s matrix",gn_rms
[0],whatname
[ewhat
]);
782 write_xpm(opt2FILE("-m",NFILE
,fnm
,"w"),0,buf
,whatlabel
[ewhat
],
783 output_env_get_time_label(oenv
),output_env_get_time_label(oenv
),tel_mat
,tel_mat2
,
784 axis
,axis2
, rmsd_mat
,rmsd_min
,rmsd_max
,rlo
,rhi
,&nlevels
);
785 /* Print the distribution of RMSD values */
786 if (opt2bSet("-dist",NFILE
,fnm
))
787 low_rmsd_dist(opt2fn("-dist",NFILE
,fnm
),rmsd_max
,tel_mat
,rmsd_mat
,oenv
);
790 snew(delta_tot
,delta_xsize
);
791 for(j
=0; j
<tel_mat
-1; j
++) {
792 for(i
=j
+1; i
<tel_mat
; i
++) {
794 if (mx
< tel_mat
/2) {
796 mx
=(int)(log(mx
)*delta_scalex
+0.5);
797 my
=(int)(rmsd_mat
[i
][j
]*delta_scaley
*del_lev
+0.5);
798 delta_tot
[mx
] += 1.0;
799 if ((rmsd_mat
[i
][j
]>=0) && (rmsd_mat
[i
][j
]<=delta_maxy
))
800 delta
[mx
][my
] += 1.0;
805 for(i
=0; i
<delta_xsize
; i
++) {
806 if (delta_tot
[i
] > 0.0) {
807 delta_tot
[i
]=1.0/delta_tot
[i
];
808 for(j
=0; j
<=del_lev
; j
++) {
809 delta
[i
][j
] *= delta_tot
[i
];
810 if (delta
[i
][j
] > delta_max
)
811 delta_max
=delta
[i
][j
];
815 fprintf(stderr
,"Maximum in delta matrix: %f\n",delta_max
);
816 snew(del_xaxis
,delta_xsize
);
817 snew(del_yaxis
,del_lev
+1);
818 for (i
=0; i
<delta_xsize
; i
++)
819 del_xaxis
[i
]=axis
[i
]-axis
[0];
820 for (i
=0; i
<del_lev
+1; i
++)
821 del_yaxis
[i
]=delta_maxy
*i
/del_lev
;
822 sprintf(buf
,"%s %s vs. delta t",gn_rms
[0],whatname
[ewhat
]);
823 fp
= ffopen("delta.xpm","w");
824 write_xpm(fp
,0,buf
,"density",output_env_get_time_label(oenv
),whatlabel
[ewhat
],
825 delta_xsize
,del_lev
+1,del_xaxis
,del_yaxis
,
826 delta
,0.0,delta_max
,rlo
,rhi
,&nlevels
);
829 if (opt2bSet("-bin",NFILE
,fnm
)) {
830 /* NB: File must be binary if we use fwrite */
831 fp
=ftp2FILE(efDAT
,NFILE
,fnm
,"wb");
832 for(i
=0;i
<tel_mat
;i
++)
833 if(fwrite(rmsd_mat
[i
],sizeof(**rmsd_mat
),tel_mat2
,fp
) != tel_mat2
)
835 gmx_fatal(FARGS
,"Error writing to output file");
841 fprintf(stderr
,"\nMin. angle: %f, Max. angle: %f\n",bond_min
,bond_max
);
842 if (bond_user_max
!= -1) bond_max
=bond_user_max
;
843 if (bond_user_min
!= -1) bond_min
=bond_user_min
;
844 if ((bond_user_max
!= -1) || (bond_user_min
!= -1))
845 fprintf(stderr
,"Bond angle Min and Max set to:\n"
846 "Min. angle: %f, Max. angle: %f\n",bond_min
,bond_max
);
847 rlo
.r
= 1; rlo
.g
= 1; rlo
.b
= 1;
848 rhi
.r
= 0; rhi
.g
= 0; rhi
.b
= 0;
849 sprintf(buf
,"%s av. bond angle deviation",gn_rms
[0]);
850 write_xpm(opt2FILE("-bm",NFILE
,fnm
,"w"),0,buf
,"degrees",
851 output_env_get_time_label(oenv
),output_env_get_time_label(oenv
),tel_mat
,tel_mat2
,
852 axis
,axis2
, bond_mat
,bond_min
,bond_max
,rlo
,rhi
,&nlevels
);
856 bAv
=opt2bSet("-a",NFILE
,fnm
);
858 /* Write the RMSD's to file */
860 sprintf(buf
,"%s",whatxvgname
[ewhat
]);
862 sprintf(buf
,"%s with frame %g %s ago",whatxvgname
[ewhat
],
863 time
[prev
*freq
]-time
[0], output_env_get_time_label(oenv
));
864 fp
=xvgropen(opt2fn("-o",NFILE
,fnm
),buf
,output_env_get_xvgr_tlabel(oenv
),
865 whatxvglabel
[ewhat
], oenv
);
866 if (output_env_get_print_xvgr_codes(oenv
))
867 fprintf(fp
,"@ subtitle \"%s%s after %s%s%s\"\n",
868 (nrms
==1)?"":"of " , gn_rms
[0], fitgraphlabel
[efit
],
869 bFit
?" to ":"" , bFit
?gn_fit
:"");
871 xvgr_legend(fp
,nrms
,gn_rms
,oenv
);
872 for(i
=0; (i
<teller
); i
++) {
873 if ( bSplit
&& i
>0 &&
874 abs(time
[bPrev
? freq
*i
: i
]/output_env_get_time_factor(oenv
))<1e-5 )
878 fprintf(fp
,"%12.7f",time
[bPrev
? freq
*i
: i
]);
879 for(j
=0; (j
<nrms
); j
++) {
880 fprintf(fp
," %12.7f",rls
[j
][i
]);
889 /* Write the mirror RMSD's to file */
890 sprintf(buf
,"%s with Mirror",whatxvgname
[ewhat
]);
891 sprintf(buf2
,"Mirror %s",whatxvglabel
[ewhat
]);
892 fp
=xvgropen(opt2fn("-mir",NFILE
,fnm
), buf
, output_env_get_xvgr_tlabel(oenv
),
895 if (output_env_get_print_xvgr_codes(oenv
))
896 fprintf(fp
,"@ subtitle \"of %s after lsq fit to mirror of %s\"\n",
900 if (output_env_get_print_xvgr_codes(oenv
))
901 fprintf(fp
,"@ subtitle \"after lsq fit to mirror %s\"\n",gn_fit
);
902 xvgr_legend(fp
,nrms
,gn_rms
,oenv
);
904 for(i
=0; (i
<teller
); i
++) {
905 if ( bSplit
&& i
>0 && abs(time
[i
])<1e-5 )
907 fprintf(fp
,"%12.7f",time
[i
]);
908 for(j
=0; (j
<nrms
); j
++)
909 fprintf(fp
," %12.7f",rlsm
[j
][i
]);
916 sprintf(buf
,"Average %s",whatxvgname
[ewhat
]);
917 sprintf(buf2
,"Average %s",whatxvglabel
[ewhat
]);
918 fp
= xvgropen(opt2fn("-a",NFILE
,fnm
), buf
, "Residue", buf2
,oenv
);
919 for(j
=0; (j
<nrms
); j
++)
920 fprintf(fp
,"%10d %10g\n",j
,rlstot
/teller
);
925 fp
= xvgropen("aver.xvg",gn_rms
[0],"Residue",whatxvglabel
[ewhat
],oenv
);
926 for(j
=0; (j
<irms
[0]); j
++)
927 fprintf(fp
,"%10d %10g\n",j
,rlsnorm
[j
]/teller
);
930 do_view(oenv
,opt2fn_null("-a",NFILE
,fnm
),"-graphtype bar");
931 do_view(oenv
,opt2fn("-o",NFILE
,fnm
),NULL
);
932 do_view(oenv
,opt2fn_null("-mir",NFILE
,fnm
),NULL
);
933 do_view(oenv
,opt2fn_null("-m",NFILE
,fnm
),NULL
);
934 do_view(oenv
,opt2fn_null("-bm",NFILE
,fnm
),NULL
);
935 do_view(oenv
,opt2fn_null("-dist",NFILE
,fnm
),NULL
);