Enforced rotation: fixed torque calculation for FLEX potential when using mass-weighting
[gromacs/adressmacs.git] / src / tools / gmx_rms.c
blob292960b6f565f07cde7d99d21647e5ecc5266c90
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 "smalloc.h"
40 #include "math.h"
41 #include "macros.h"
42 #include "typedefs.h"
43 #include "xvgr.h"
44 #include "copyrite.h"
45 #include "statutil.h"
46 #include "string2.h"
47 #include "vec.h"
48 #include "index.h"
49 #include "gmx_fatal.h"
50 #include "futil.h"
51 #include "princ.h"
52 #include "rmpbc.h"
53 #include "do_fit.h"
54 #include "matio.h"
55 #include "tpxio.h"
56 #include "cmat.h"
57 #include "viewit.h"
58 #include "gmx_ana.h"
61 static void norm_princ(t_atoms *atoms, int isize, atom_id *index, int natoms,
62 rvec *x)
64 int i, m;
65 rvec princ, vec;
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 */
72 clear_rvec(vec);
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++)
87 x[i][m] *= vec[m];
92 int gmx_rms(int argc, char *argv[])
94 const char
95 *desc[] =
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 gmx_bool bPBC = TRUE, bFitAll = TRUE, bSplit = FALSE;
143 static gmx_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 */
148 enum
150 ewSel, ewRMSD, ewRho, ewRhoSc, ewNR
152 int ewhat;
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 */
164 enum
166 efSel, efFit, efReset, efNone, efNR
168 int efit;
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" };
173 static int nrms = 1;
174 static gmx_bool bMassWeighted = TRUE;
175 t_pargs pa[] =
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,
208 { &bDeltaLog },
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,
213 { &avl },
214 "HIDDENAverage over this distance in the RMSD matrix" } };
215 int natoms_trx, natoms_trx2, natoms;
216 int i, j, k, m, teller, teller2, tel_mat, tel_mat2;
217 #define NFRAME 5000
218 int maxframe = NFRAME, maxframe2 = NFRAME;
219 real t, *w_rls, *w_rms, *w_rls_m = NULL, *w_rms_m = NULL;
220 gmx_bool bNorm, bAv, bFreq2, bFile2, bMat, bBond, bDelta, bMirror, bMass;
221 gmx_bool bFit, bReset;
222 t_topology top;
223 int ePBC;
224 t_iatom *iatom = NULL;
226 matrix box;
227 rvec *x, *xp, *xm = NULL, **mat_x = NULL, **mat_x2, *mat_x2_j = NULL, vec1,
228 vec2;
229 t_trxstatus *status;
230 char buf[256], buf2[256];
231 int ncons = 0;
232 FILE *fp;
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,
238 *delta_tot;
239 int delta_xsize = 0, del_lev = 100, mx, my, abs_my;
240 gmx_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 =
244 NULL;
245 char *gn_fit, **gn_rms;
246 t_rgb rlo, rhi;
247 output_env_t oenv;
248 gmx_rmpbc_t gpbc=NULL;
250 t_filenm fnm[] =
252 { efTPS, NULL, NULL, ffREAD },
253 { efTRX, "-f", NULL, ffREAD },
254 { efTRX, "-f2", NULL, ffOPTRD },
255 { efNDX, NULL, NULL, ffOPTRD },
256 { efXVG, NULL, "rmsd", ffWRITE },
257 { efXVG, "-mir", "rmsdmir", ffOPTWR },
258 { efXVG, "-a", "avgrp", ffOPTWR },
259 { efXVG, "-dist", "rmsd-dist", ffOPTWR },
260 { efXPM, "-m", "rmsd", ffOPTWR },
261 { efDAT, "-bin", "rmsd", ffOPTWR },
262 { efXPM, "-bm", "bond", ffOPTWR } };
263 #define NFILE asize(fnm)
265 CopyRight(stderr, argv[0]);
266 parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_TIME_UNIT | PCA_CAN_VIEW
267 | PCA_BE_NICE, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL,
268 &oenv);
269 /* parse enumerated options: */
270 ewhat = nenum(what);
271 if (ewhat == ewRho || ewhat == ewRhoSc)
272 please_cite(stdout, "Maiorov95");
273 efit = nenum(fit);
274 bFit = efit == efFit;
275 bReset = efit == efReset;
276 if (bFit)
278 bReset = TRUE; /* for fit, reset *must* be set */
280 else
282 bFitAll = FALSE;
285 /* mark active cmdline options */
286 bMirror = opt2bSet("-mir", NFILE, fnm); /* calc RMSD vs mirror of ref. */
287 bFile2 = opt2bSet("-f2", NFILE, fnm);
288 bMat = opt2bSet("-m", NFILE, fnm);
289 bBond = opt2bSet("-bm", NFILE, fnm);
290 bDelta = (delta_maxy > 0); /* calculate rmsd vs delta t matrix from *
291 * your RMSD matrix (hidden option */
292 bNorm = opt2bSet("-a", NFILE, fnm);
293 bFreq2 = opt2parg_bSet("-skip2", asize(pa), pa);
294 if (freq <= 0)
296 fprintf(stderr, "The number of frames to skip is <= 0. "
297 "Writing out all frames.\n\n");
298 freq = 1;
300 if (!bFreq2)
302 freq2 = freq;
304 else if (bFile2 && freq2 <= 0)
306 fprintf(stderr,
307 "The number of frames to skip in second trajectory is <= 0.\n"
308 " Writing out all frames.\n\n");
309 freq2 = 1;
312 bPrev = (prev > 0);
313 if (bPrev)
315 prev = abs(prev);
316 if (freq != 1)
317 fprintf(stderr, "WARNING: option -skip also applies to -prev\n");
320 if (bFile2 && !bMat && !bBond)
322 fprintf(
323 stderr,
324 "WARNING: second trajectory (-f2) useless when not calculating matrix (-m/-bm),\n"
325 " will not read from %s\n", opt2fn("-f2", NFILE,
326 fnm));
327 bFile2 = FALSE;
330 if (bDelta)
332 bMat = TRUE;
333 if (bFile2)
335 fprintf(stderr,
336 "WARNING: second trajectory (-f2) useless when making delta matrix,\n"
337 " will not read from %s\n", opt2fn("-f2",
338 NFILE, fnm));
339 bFile2 = FALSE;
343 bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), buf, &top, &ePBC, &xp,
344 NULL, box, TRUE);
345 snew(w_rls,top.atoms.nr);
346 snew(w_rms,top.atoms.nr);
348 if (!bTop && bBond)
350 fprintf(stderr,
351 "WARNING: Need a run input file for bond angle matrix,\n"
352 " will not calculate bond angle matrix.\n");
353 bBond = FALSE;
356 if (bReset)
358 fprintf(stderr, "Select group for %s fit\n", bFit ? "least squares"
359 : "translational");
360 get_index(&(top.atoms), ftp2fn_null(efNDX, NFILE, fnm), 1, &ifit,
361 &ind_fit, &gn_fit);
363 else
364 ifit = 0;
366 if (bReset)
368 if (bFit && ifit < 3)
369 gmx_fatal(FARGS,"Need >= 3 points to fit!\n" );
371 bMass = FALSE;
372 for(i=0; i<ifit; i++)
374 if (bMassWeighted)
375 w_rls[ind_fit[i]] = top.atoms.atom[ind_fit[i]].m;
376 else
377 w_rls[ind_fit[i]] = 1;
378 bMass = bMass || (top.atoms.atom[ind_fit[i]].m != 0);
380 if (!bMass)
382 fprintf(stderr,"All masses in the fit group are 0, using masses of 1\n");
383 for(i=0; i<ifit; i++)
385 w_rls[ind_fit[i]] = 1;
390 if (bMat || bBond)
391 nrms=1;
393 snew(gn_rms,nrms);
394 snew(ind_rms,nrms);
395 snew(irms,nrms);
397 fprintf(stderr,"Select group%s for %s calculation\n",
398 (nrms>1) ? "s" : "",whatname[ewhat]);
399 get_index(&(top.atoms),ftp2fn_null(efNDX,NFILE,fnm),
400 nrms,irms,ind_rms,gn_rms);
402 if (bNorm)
404 snew(rlsnorm,irms[0]);
406 snew(rls,nrms);
407 for(j=0; j<nrms; j++)
408 snew(rls[j],maxframe);
409 if (bMirror)
411 snew(rlsm,nrms);
412 for(j=0; j<nrms; j++)
413 snew(rlsm[j],maxframe);
415 snew(time,maxframe);
416 for(j=0; j<nrms; j++)
418 bMass = FALSE;
419 for(i=0; i<irms[j]; i++)
421 if (bMassWeighted)
422 w_rms[ind_rms[j][i]] = top.atoms.atom[ind_rms[j][i]].m;
423 else
424 w_rms[ind_rms[j][i]] = 1.0;
425 bMass = bMass || (top.atoms.atom[ind_rms[j][i]].m != 0);
427 if (!bMass) {
428 fprintf(stderr,"All masses in group %d are 0, using masses of 1\n",j);
429 for(i=0; i<irms[j]; i++)
430 w_rms[ind_rms[j][i]] = 1;
433 /* Prepare reference frame */
434 if (bPBC) {
435 gpbc = gmx_rmpbc_init(&top.idef,ePBC,top.atoms.nr,box);
436 gmx_rmpbc(gpbc,top.atoms.nr,box,xp);
438 if (bReset)
439 reset_x(ifit,ind_fit,top.atoms.nr,NULL,xp,w_rls);
440 if (bMirror) {
441 /* generate reference structure mirror image: */
442 snew(xm, top.atoms.nr);
443 for(i=0; i<top.atoms.nr; i++) {
444 copy_rvec(xp[i],xm[i]);
445 xm[i][XX] = -xm[i][XX];
448 if (ewhat==ewRhoSc)
449 norm_princ(&top.atoms, ifit, ind_fit, top.atoms.nr, xp);
451 /* read first frame */
452 natoms_trx=read_first_x(oenv,&status,opt2fn("-f",NFILE,fnm),&t,&x,box);
453 if (natoms_trx != top.atoms.nr)
454 fprintf(stderr,
455 "\nWARNING: topology has %d atoms, whereas trajectory has %d\n",
456 top.atoms.nr,natoms_trx);
457 natoms = min(top.atoms.nr,natoms_trx);
458 if (bMat || bBond || bPrev) {
459 snew(mat_x,NFRAME);
461 if (bPrev)
462 /* With -prev we use all atoms for simplicity */
463 n_ind_m = natoms;
464 else {
465 /* Check which atoms we need (fit/rms) */
466 snew(bInMat,natoms);
467 for(i=0; i<ifit; i++)
468 bInMat[ind_fit[i]] = TRUE;
469 n_ind_m=ifit;
470 for(i=0; i<irms[0]; i++)
471 if (!bInMat[ind_rms[0][i]]) {
472 bInMat[ind_rms[0][i]] = TRUE;
473 n_ind_m++;
476 /* Make an index of needed atoms */
477 snew(ind_m,n_ind_m);
478 snew(rev_ind_m,natoms);
479 j = 0;
480 for(i=0; i<natoms; i++)
481 if (bPrev || bInMat[i]) {
482 ind_m[j] = i;
483 rev_ind_m[i] = j;
484 j++;
486 snew(w_rls_m,n_ind_m);
487 snew(ind_rms_m,irms[0]);
488 snew(w_rms_m,n_ind_m);
489 for(i=0; i<ifit; i++)
490 w_rls_m[rev_ind_m[ind_fit[i]]] = w_rls[ind_fit[i]];
491 for(i=0; i<irms[0]; i++) {
492 ind_rms_m[i] = rev_ind_m[ind_rms[0][i]];
493 w_rms_m[ind_rms_m[i]] = w_rms[ind_rms[0][i]];
495 sfree(bInMat);
498 if (bBond) {
499 ncons = 0;
500 for(k=0; k<F_NRE; k++)
501 if (IS_CHEMBOND(k)) {
502 iatom = top.idef.il[k].iatoms;
503 ncons += top.idef.il[k].nr/3;
505 fprintf(stderr,"Found %d bonds in topology\n",ncons);
506 snew(ind_bond1,ncons);
507 snew(ind_bond2,ncons);
508 ibond=0;
509 for(k=0; k<F_NRE; k++)
510 if (IS_CHEMBOND(k)) {
511 iatom = top.idef.il[k].iatoms;
512 ncons = top.idef.il[k].nr/3;
513 for (i=0; i<ncons; i++) {
514 bA1=FALSE;
515 bA2=FALSE;
516 for (j=0; j<irms[0]; j++) {
517 if (iatom[3*i+1] == ind_rms[0][j]) bA1=TRUE;
518 if (iatom[3*i+2] == ind_rms[0][j]) bA2=TRUE;
520 if (bA1 && bA2) {
521 ind_bond1[ibond] = rev_ind_m[iatom[3*i+1]];
522 ind_bond2[ibond] = rev_ind_m[iatom[3*i+2]];
523 ibond++;
527 fprintf(stderr,"Using %d bonds for bond angle matrix\n",ibond);
528 if (ibond==0)
529 gmx_fatal(FARGS,"0 bonds found");
532 /* start looping over frames: */
533 tel_mat = 0;
534 teller = 0;
535 do {
536 if (bPBC)
537 gmx_rmpbc(gpbc,natoms,box,x);
539 if (bReset)
540 reset_x(ifit,ind_fit,natoms,NULL,x,w_rls);
541 if (ewhat==ewRhoSc)
542 norm_princ(&top.atoms, ifit, ind_fit, natoms, x);
544 if (bFit)
545 /*do the least squares fit to original structure*/
546 do_fit(natoms,w_rls,xp,x);
548 if (teller % freq == 0) {
549 /* keep frame for matrix calculation */
550 if (bMat || bBond || bPrev) {
551 if (tel_mat >= NFRAME)
552 srenew(mat_x,tel_mat+1);
553 snew(mat_x[tel_mat],n_ind_m);
554 for (i=0;i<n_ind_m;i++)
555 copy_rvec(x[ind_m[i]],mat_x[tel_mat][i]);
557 tel_mat++;
560 /*calculate energy of root_least_squares*/
561 if (bPrev) {
562 j=tel_mat-prev-1;
563 if (j<0)
564 j=0;
565 for (i=0;i<n_ind_m;i++)
566 copy_rvec(mat_x[j][i],xp[ind_m[i]]);
567 if (bReset)
568 reset_x(ifit,ind_fit,natoms,NULL,xp,w_rls);
569 if (bFit)
570 do_fit(natoms,w_rls,x,xp);
572 for(j=0; (j<nrms); j++)
573 rls[j][teller] =
574 calc_similar_ind(ewhat!=ewRMSD,irms[j],ind_rms[j],w_rms,x,xp);
575 if (bNorm) {
576 for(j=0; (j<irms[0]); j++)
577 rlsnorm[j] +=
578 calc_similar_ind(ewhat!=ewRMSD,1,&(ind_rms[0][j]),w_rms,x,xp);
581 if (bMirror) {
582 if (bFit)
583 /*do the least squares fit to mirror of original structure*/
584 do_fit(natoms,w_rls,xm,x);
586 for(j=0; j<nrms; j++)
587 rlsm[j][teller] =
588 calc_similar_ind(ewhat!=ewRMSD,irms[j],ind_rms[j],w_rms,x,xm);
590 time[teller]=output_env_conv_time(oenv,t);
592 teller++;
593 if (teller >= maxframe) {
594 maxframe +=NFRAME;
595 srenew(time,maxframe);
596 for(j=0; (j<nrms); j++)
597 srenew(rls[j],maxframe);
598 if (bMirror)
599 for(j=0; (j<nrms); j++)
600 srenew(rlsm[j],maxframe);
602 } while (read_next_x(oenv,status,&t,natoms_trx,x,box));
603 close_trj(status);
605 if (bFile2) {
606 snew(time2,maxframe2);
608 fprintf(stderr,"\nWill read second trajectory file\n");
609 snew(mat_x2,NFRAME);
610 natoms_trx2 =
611 read_first_x(oenv,&status,opt2fn("-f2",NFILE,fnm),&t,&x,box);
612 if ( natoms_trx2 != natoms_trx )
613 gmx_fatal(FARGS,
614 "Second trajectory (%d atoms) does not match the first one"
615 " (%d atoms)", natoms_trx2, natoms_trx);
616 tel_mat2 = 0;
617 teller2 = 0;
618 do {
619 if (bPBC)
620 gmx_rmpbc(gpbc,natoms,box,x);
622 if (bReset)
623 reset_x(ifit,ind_fit,natoms,NULL,x,w_rls);
624 if (ewhat==ewRhoSc)
625 norm_princ(&top.atoms, ifit, ind_fit, natoms, x);
627 if (bFit)
628 /*do the least squares fit to original structure*/
629 do_fit(natoms,w_rls,xp,x);
631 if (teller2 % freq2 == 0) {
632 /* keep frame for matrix calculation */
633 if (bMat) {
634 if (tel_mat2 >= NFRAME)
635 srenew(mat_x2,tel_mat2+1);
636 snew(mat_x2[tel_mat2],n_ind_m);
637 for (i=0;i<n_ind_m;i++)
638 copy_rvec(x[ind_m[i]],mat_x2[tel_mat2][i]);
640 tel_mat2++;
643 time2[teller2]=output_env_conv_time(oenv,t);
645 teller2++;
646 if (teller2 >= maxframe2) {
647 maxframe2 +=NFRAME;
648 srenew(time2,maxframe2);
650 } while (read_next_x(oenv,status,&t,natoms_trx2,x,box));
651 close_trj(status);
652 } else {
653 mat_x2=mat_x;
654 time2=time;
655 tel_mat2=tel_mat;
656 freq2=freq;
658 gmx_rmpbc_done(gpbc);
660 if (bMat || bBond) {
661 /* calculate RMS matrix */
662 fprintf(stderr,"\n");
663 if (bMat) {
664 fprintf(stderr,"Building %s matrix, %dx%d elements\n",
665 whatname[ewhat],tel_mat,tel_mat2);
666 snew(rmsd_mat,tel_mat);
668 if (bBond) {
669 fprintf(stderr,"Building bond angle matrix, %dx%d elements\n",
670 tel_mat,tel_mat2);
671 snew(bond_mat,tel_mat);
673 snew(axis,tel_mat);
674 snew(axis2,tel_mat2);
675 rmsd_max=0;
676 if (bFile2)
677 rmsd_min=1e10;
678 else
679 rmsd_min=0;
680 rmsd_avg=0;
681 bond_max=0;
682 bond_min=1e10;
683 for(j=0; j<tel_mat2; j++)
684 axis2[j]=time2[freq2*j];
685 if (bDelta) {
686 if (bDeltaLog) {
687 delta_scalex=8.0/log(2.0);
688 delta_xsize=(int)(log(tel_mat/2)*delta_scalex+0.5)+1;
690 else {
691 delta_xsize=tel_mat/2;
693 delta_scaley=1.0/delta_maxy;
694 snew(delta,delta_xsize);
695 for(j=0; j<delta_xsize; j++)
696 snew(delta[j],del_lev+1);
697 if (avl > 0) {
698 snew(rmsdav_mat,tel_mat);
699 for(j=0; j<tel_mat; j++)
700 snew(rmsdav_mat[j],tel_mat);
704 if (bFitAll)
705 snew(mat_x2_j,natoms);
706 for(i=0; i<tel_mat; i++) {
707 axis[i]=time[freq*i];
708 fprintf(stderr,"\r element %5d; time %5.2f ",i,axis[i]);
709 if (bMat) snew(rmsd_mat[i],tel_mat2);
710 if (bBond) snew(bond_mat[i],tel_mat2);
711 for(j=0; j<tel_mat2; j++) {
712 if (bFitAll) {
713 for (k=0;k<n_ind_m;k++)
714 copy_rvec(mat_x2[j][k],mat_x2_j[k]);
715 do_fit(n_ind_m,w_rls_m,mat_x[i],mat_x2_j);
716 } else
717 mat_x2_j=mat_x2[j];
718 if (bMat) {
719 if (bFile2 || (i<j)) {
720 rmsd_mat[i][j] =
721 calc_similar_ind(ewhat!=ewRMSD,irms[0],ind_rms_m,
722 w_rms_m,mat_x[i],mat_x2_j);
723 if (rmsd_mat[i][j] > rmsd_max) rmsd_max=rmsd_mat[i][j];
724 if (rmsd_mat[i][j] < rmsd_min) rmsd_min=rmsd_mat[i][j];
725 rmsd_avg += rmsd_mat[i][j];
726 } else
727 rmsd_mat[i][j]=rmsd_mat[j][i];
729 if (bBond) {
730 if (bFile2 || (i<=j)) {
731 ang=0.0;
732 for(m=0;m<ibond;m++) {
733 rvec_sub(mat_x[i][ind_bond1[m]],mat_x[i][ind_bond2[m]],vec1);
734 rvec_sub(mat_x2_j[ind_bond1[m]],mat_x2_j[ind_bond2[m]],vec2);
735 ang += acos(cos_angle(vec1,vec2));
737 bond_mat[i][j]=ang*180.0/(M_PI*ibond);
738 if (bond_mat[i][j] > bond_max) bond_max=bond_mat[i][j];
739 if (bond_mat[i][j] < bond_min) bond_min=bond_mat[i][j];
741 else
742 bond_mat[i][j]=bond_mat[j][i];
746 if (bFile2)
747 rmsd_avg /= tel_mat*tel_mat2;
748 else
749 rmsd_avg /= tel_mat*(tel_mat - 1)/2;
750 if (bMat && (avl > 0)) {
751 rmsd_max=0.0;
752 rmsd_min=0.0;
753 rmsd_avg=0.0;
754 for(j=0; j<tel_mat-1; j++) {
755 for(i=j+1; i<tel_mat; i++) {
756 av_tot=0;
757 weight_tot=0;
758 for (my=-avl; my<=avl; my++) {
759 if ((j+my>=0) && (j+my<tel_mat)) {
760 abs_my = abs(my);
761 for (mx=-avl; mx<=avl; mx++) {
762 if ((i+mx>=0) && (i+mx<tel_mat)) {
763 weight = (real)(avl+1-max(abs(mx),abs_my));
764 av_tot += weight*rmsd_mat[i+mx][j+my];
765 weight_tot+=weight;
770 rmsdav_mat[i][j] = av_tot/weight_tot;
771 rmsdav_mat[j][i] = rmsdav_mat[i][j];
772 if (rmsdav_mat[i][j] > rmsd_max) rmsd_max=rmsdav_mat[i][j];
775 rmsd_mat=rmsdav_mat;
778 if (bMat) {
779 fprintf(stderr,"\n%s: Min %f, Max %f, Avg %f\n",
780 whatname[ewhat],rmsd_min,rmsd_max,rmsd_avg);
781 rlo.r = 1; rlo.g = 1; rlo.b = 1;
782 rhi.r = 0; rhi.g = 0; rhi.b = 0;
783 if (rmsd_user_max != -1) rmsd_max=rmsd_user_max;
784 if (rmsd_user_min != -1) rmsd_min=rmsd_user_min;
785 if ((rmsd_user_max != -1) || (rmsd_user_min != -1))
786 fprintf(stderr,"Min and Max value set to resp. %f and %f\n",
787 rmsd_min,rmsd_max);
788 sprintf(buf,"%s %s matrix",gn_rms[0],whatname[ewhat]);
789 write_xpm(opt2FILE("-m",NFILE,fnm,"w"),0,buf,whatlabel[ewhat],
790 output_env_get_time_label(oenv),output_env_get_time_label(oenv),tel_mat,tel_mat2,
791 axis,axis2, rmsd_mat,rmsd_min,rmsd_max,rlo,rhi,&nlevels);
792 /* Print the distribution of RMSD values */
793 if (opt2bSet("-dist",NFILE,fnm))
794 low_rmsd_dist(opt2fn("-dist",NFILE,fnm),rmsd_max,tel_mat,rmsd_mat,oenv);
796 if (bDelta) {
797 snew(delta_tot,delta_xsize);
798 for(j=0; j<tel_mat-1; j++) {
799 for(i=j+1; i<tel_mat; i++) {
800 mx=i-j ;
801 if (mx < tel_mat/2) {
802 if (bDeltaLog)
803 mx=(int)(log(mx)*delta_scalex+0.5);
804 my=(int)(rmsd_mat[i][j]*delta_scaley*del_lev+0.5);
805 delta_tot[mx] += 1.0;
806 if ((rmsd_mat[i][j]>=0) && (rmsd_mat[i][j]<=delta_maxy))
807 delta[mx][my] += 1.0;
811 delta_max=0;
812 for(i=0; i<delta_xsize; i++) {
813 if (delta_tot[i] > 0.0) {
814 delta_tot[i]=1.0/delta_tot[i];
815 for(j=0; j<=del_lev; j++) {
816 delta[i][j] *= delta_tot[i];
817 if (delta[i][j] > delta_max)
818 delta_max=delta[i][j];
822 fprintf(stderr,"Maximum in delta matrix: %f\n",delta_max);
823 snew(del_xaxis,delta_xsize);
824 snew(del_yaxis,del_lev+1);
825 for (i=0; i<delta_xsize; i++)
826 del_xaxis[i]=axis[i]-axis[0];
827 for (i=0; i<del_lev+1; i++)
828 del_yaxis[i]=delta_maxy*i/del_lev;
829 sprintf(buf,"%s %s vs. delta t",gn_rms[0],whatname[ewhat]);
830 fp = ffopen("delta.xpm","w");
831 write_xpm(fp,0,buf,"density",output_env_get_time_label(oenv),whatlabel[ewhat],
832 delta_xsize,del_lev+1,del_xaxis,del_yaxis,
833 delta,0.0,delta_max,rlo,rhi,&nlevels);
834 ffclose(fp);
836 if (opt2bSet("-bin",NFILE,fnm)) {
837 /* NB: File must be binary if we use fwrite */
838 fp=ftp2FILE(efDAT,NFILE,fnm,"wb");
839 for(i=0;i<tel_mat;i++)
840 if(fwrite(rmsd_mat[i],sizeof(**rmsd_mat),tel_mat2,fp) != tel_mat2)
842 gmx_fatal(FARGS,"Error writing to output file");
844 ffclose(fp);
847 if (bBond) {
848 fprintf(stderr,"\nMin. angle: %f, Max. angle: %f\n",bond_min,bond_max);
849 if (bond_user_max != -1) bond_max=bond_user_max;
850 if (bond_user_min != -1) bond_min=bond_user_min;
851 if ((bond_user_max != -1) || (bond_user_min != -1))
852 fprintf(stderr,"Bond angle Min and Max set to:\n"
853 "Min. angle: %f, Max. angle: %f\n",bond_min,bond_max);
854 rlo.r = 1; rlo.g = 1; rlo.b = 1;
855 rhi.r = 0; rhi.g = 0; rhi.b = 0;
856 sprintf(buf,"%s av. bond angle deviation",gn_rms[0]);
857 write_xpm(opt2FILE("-bm",NFILE,fnm,"w"),0,buf,"degrees",
858 output_env_get_time_label(oenv),output_env_get_time_label(oenv),tel_mat,tel_mat2,
859 axis,axis2, bond_mat,bond_min,bond_max,rlo,rhi,&nlevels);
863 bAv=opt2bSet("-a",NFILE,fnm);
865 /* Write the RMSD's to file */
866 if (!bPrev)
867 sprintf(buf,"%s",whatxvgname[ewhat]);
868 else
869 sprintf(buf,"%s with frame %g %s ago",whatxvgname[ewhat],
870 time[prev*freq]-time[0], output_env_get_time_label(oenv));
871 fp=xvgropen(opt2fn("-o",NFILE,fnm),buf,output_env_get_xvgr_tlabel(oenv),
872 whatxvglabel[ewhat], oenv);
873 if (output_env_get_print_xvgr_codes(oenv))
874 fprintf(fp,"@ subtitle \"%s%s after %s%s%s\"\n",
875 (nrms==1)?"":"of " , gn_rms[0], fitgraphlabel[efit],
876 bFit ?" to ":"" , bFit?gn_fit:"");
877 if (nrms != 1)
878 xvgr_legend(fp,nrms,(const char**)gn_rms,oenv);
879 for(i=0; (i<teller); i++) {
880 if ( bSplit && i>0 &&
881 abs(time[bPrev ? freq*i : i]/output_env_get_time_factor(oenv))<1e-5 )
883 fprintf(fp,"&\n");
885 fprintf(fp,"%12.7f",time[bPrev ? freq*i : i]);
886 for(j=0; (j<nrms); j++) {
887 fprintf(fp," %12.7f",rls[j][i]);
888 if (bAv)
889 rlstot+=rls[j][i];
891 fprintf(fp,"\n");
893 ffclose(fp);
895 if (bMirror) {
896 /* Write the mirror RMSD's to file */
897 sprintf(buf,"%s with Mirror",whatxvgname[ewhat]);
898 sprintf(buf2,"Mirror %s",whatxvglabel[ewhat]);
899 fp=xvgropen(opt2fn("-mir",NFILE,fnm), buf, output_env_get_xvgr_tlabel(oenv),
900 buf2,oenv);
901 if (nrms == 1) {
902 if (output_env_get_print_xvgr_codes(oenv))
903 fprintf(fp,"@ subtitle \"of %s after lsq fit to mirror of %s\"\n",
904 gn_rms[0],gn_fit);
906 else {
907 if (output_env_get_print_xvgr_codes(oenv))
908 fprintf(fp,"@ subtitle \"after lsq fit to mirror %s\"\n",gn_fit);
909 xvgr_legend(fp,nrms,(const char**)gn_rms,oenv);
911 for(i=0; (i<teller); i++) {
912 if ( bSplit && i>0 && abs(time[i])<1e-5 )
913 fprintf(fp,"&\n");
914 fprintf(fp,"%12.7f",time[i]);
915 for(j=0; (j<nrms); j++)
916 fprintf(fp," %12.7f",rlsm[j][i]);
917 fprintf(fp,"\n");
919 ffclose(fp);
922 if (bAv) {
923 sprintf(buf,"Average %s",whatxvgname[ewhat]);
924 sprintf(buf2,"Average %s",whatxvglabel[ewhat]);
925 fp = xvgropen(opt2fn("-a",NFILE,fnm), buf, "Residue", buf2,oenv);
926 for(j=0; (j<nrms); j++)
927 fprintf(fp,"%10d %10g\n",j,rlstot/teller);
928 ffclose(fp);
931 if (bNorm) {
932 fp = xvgropen("aver.xvg",gn_rms[0],"Residue",whatxvglabel[ewhat],oenv);
933 for(j=0; (j<irms[0]); j++)
934 fprintf(fp,"%10d %10g\n",j,rlsnorm[j]/teller);
935 ffclose(fp);
937 do_view(oenv,opt2fn_null("-a",NFILE,fnm),"-graphtype bar");
938 do_view(oenv,opt2fn("-o",NFILE,fnm),NULL);
939 do_view(oenv,opt2fn_null("-mir",NFILE,fnm),NULL);
940 do_view(oenv,opt2fn_null("-m",NFILE,fnm),NULL);
941 do_view(oenv,opt2fn_null("-bm",NFILE,fnm),NULL);
942 do_view(oenv,opt2fn_null("-dist",NFILE,fnm),NULL);
944 thanx(stderr);
946 return 0;