gmx_rmpbc gets natoms passed again, without natoms many tool could not parse trajecto...
[gromacs.git] / src / tools / gmx_rms.c
blob5a36160fa551f2a3954a53216d53031fcdd6020d
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 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 */
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 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, natoms2;
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 bool bNorm, bAv, bFreq2, bFile2, bMat, bBond, bDelta, bMirror, bMass;
221 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 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=read_first_x(oenv,&status,opt2fn("-f",NFILE,fnm),&t,&x,box);
453 if (natoms != top.atoms.nr)
454 fprintf(stderr,
455 "\nWARNING: topology has %d atoms, whereas trajectory has %d\n",
456 top.atoms.nr,natoms);
457 if (bMat || bBond || bPrev) {
458 snew(mat_x,NFRAME);
460 if (bPrev)
461 /* With -prev we use all atoms for simplicity */
462 n_ind_m = natoms;
463 else {
464 /* Check which atoms we need (fit/rms) */
465 snew(bInMat,natoms);
466 for(i=0; i<ifit; i++)
467 bInMat[ind_fit[i]] = TRUE;
468 n_ind_m=ifit;
469 for(i=0; i<irms[0]; i++)
470 if (!bInMat[ind_rms[0][i]]) {
471 bInMat[ind_rms[0][i]] = TRUE;
472 n_ind_m++;
475 /* Make an index of needed atoms */
476 snew(ind_m,n_ind_m);
477 snew(rev_ind_m,natoms);
478 j = 0;
479 for(i=0; i<natoms; i++)
480 if (bPrev || bInMat[i]) {
481 ind_m[j] = i;
482 rev_ind_m[i] = j;
483 j++;
485 snew(w_rls_m,n_ind_m);
486 snew(ind_rms_m,irms[0]);
487 snew(w_rms_m,n_ind_m);
488 for(i=0; i<ifit; i++)
489 w_rls_m[rev_ind_m[ind_fit[i]]] = w_rls[ind_fit[i]];
490 for(i=0; i<irms[0]; i++) {
491 ind_rms_m[i] = rev_ind_m[ind_rms[0][i]];
492 w_rms_m[ind_rms_m[i]] = w_rms[ind_rms[0][i]];
494 sfree(bInMat);
497 if (bBond) {
498 ncons = 0;
499 for(k=0; k<F_NRE; k++)
500 if (IS_CHEMBOND(k)) {
501 iatom = top.idef.il[k].iatoms;
502 ncons += top.idef.il[k].nr/3;
504 fprintf(stderr,"Found %d bonds in topology\n",ncons);
505 snew(ind_bond1,ncons);
506 snew(ind_bond2,ncons);
507 ibond=0;
508 for(k=0; k<F_NRE; k++)
509 if (IS_CHEMBOND(k)) {
510 iatom = top.idef.il[k].iatoms;
511 ncons = top.idef.il[k].nr/3;
512 for (i=0; i<ncons; i++) {
513 bA1=FALSE;
514 bA2=FALSE;
515 for (j=0; j<irms[0]; j++) {
516 if (iatom[3*i+1] == ind_rms[0][j]) bA1=TRUE;
517 if (iatom[3*i+2] == ind_rms[0][j]) bA2=TRUE;
519 if (bA1 && bA2) {
520 ind_bond1[ibond] = rev_ind_m[iatom[3*i+1]];
521 ind_bond2[ibond] = rev_ind_m[iatom[3*i+2]];
522 ibond++;
526 fprintf(stderr,"Using %d bonds for bond angle matrix\n",ibond);
527 if (ibond==0)
528 gmx_fatal(FARGS,"0 bonds found");
531 /* start looping over frames: */
532 tel_mat = 0;
533 teller = 0;
534 do {
535 if (bPBC)
536 gmx_rmpbc(gpbc,natoms,box,x);
538 if (bReset)
539 reset_x(ifit,ind_fit,natoms,NULL,x,w_rls);
540 if (ewhat==ewRhoSc)
541 norm_princ(&top.atoms, ifit, ind_fit, natoms, x);
543 if (bFit)
544 /*do the least squares fit to original structure*/
545 do_fit(natoms,w_rls,xp,x);
547 if (teller % freq == 0) {
548 /* keep frame for matrix calculation */
549 if (bMat || bBond || bPrev) {
550 if (tel_mat >= NFRAME)
551 srenew(mat_x,tel_mat+1);
552 snew(mat_x[tel_mat],n_ind_m);
553 for (i=0;i<n_ind_m;i++)
554 copy_rvec(x[ind_m[i]],mat_x[tel_mat][i]);
556 tel_mat++;
559 /*calculate energy of root_least_squares*/
560 if (bPrev) {
561 j=tel_mat-prev-1;
562 if (j<0)
563 j=0;
564 for (i=0;i<n_ind_m;i++)
565 copy_rvec(mat_x[j][i],xp[ind_m[i]]);
566 if (bReset)
567 reset_x(ifit,ind_fit,natoms,NULL,xp,w_rls);
568 if (bFit)
569 do_fit(natoms,w_rls,x,xp);
571 for(j=0; (j<nrms); j++)
572 rls[j][teller] =
573 calc_similar_ind(ewhat!=ewRMSD,irms[j],ind_rms[j],w_rms,x,xp);
574 if (bNorm) {
575 for(j=0; (j<irms[0]); j++)
576 rlsnorm[j] +=
577 calc_similar_ind(ewhat!=ewRMSD,1,&(ind_rms[0][j]),w_rms,x,xp);
580 if (bMirror) {
581 if (bFit)
582 /*do the least squares fit to mirror of original structure*/
583 do_fit(natoms,w_rls,xm,x);
585 for(j=0; j<nrms; j++)
586 rlsm[j][teller] =
587 calc_similar_ind(ewhat!=ewRMSD,irms[j],ind_rms[j],w_rms,x,xm);
589 time[teller]=output_env_conv_time(oenv,t);
591 teller++;
592 if (teller >= maxframe) {
593 maxframe +=NFRAME;
594 srenew(time,maxframe);
595 for(j=0; (j<nrms); j++)
596 srenew(rls[j],maxframe);
597 if (bMirror)
598 for(j=0; (j<nrms); j++)
599 srenew(rlsm[j],maxframe);
601 } while (read_next_x(oenv,status,&t,natoms,x,box));
602 close_trj(status);
604 if (bFile2) {
605 snew(time2,maxframe2);
607 fprintf(stderr,"\nWill read second trajectory file\n");
608 snew(mat_x2,NFRAME);
609 natoms2=read_first_x(oenv,&status,opt2fn("-f2",NFILE,fnm),&t,&x,box);
610 if ( natoms2 != natoms )
611 gmx_fatal(FARGS,
612 "Second trajectory (%d atoms) does not match the first one"
613 " (%d atoms)", natoms2, natoms);
614 tel_mat2 = 0;
615 teller2 = 0;
616 do {
617 if (bPBC)
618 gmx_rmpbc(gpbc,natoms,box,x);
620 if (bReset)
621 reset_x(ifit,ind_fit,natoms,NULL,x,w_rls);
622 if (ewhat==ewRhoSc)
623 norm_princ(&top.atoms, ifit, ind_fit, natoms, x);
625 if (bFit)
626 /*do the least squares fit to original structure*/
627 do_fit(natoms,w_rls,xp,x);
629 if (teller2 % freq2 == 0) {
630 /* keep frame for matrix calculation */
631 if (bMat) {
632 if (tel_mat2 >= NFRAME)
633 srenew(mat_x2,tel_mat2+1);
634 snew(mat_x2[tel_mat2],n_ind_m);
635 for (i=0;i<n_ind_m;i++)
636 copy_rvec(x[ind_m[i]],mat_x2[tel_mat2][i]);
638 tel_mat2++;
641 time2[teller2]=output_env_conv_time(oenv,t);
643 teller2++;
644 if (teller2 >= maxframe2) {
645 maxframe2 +=NFRAME;
646 srenew(time2,maxframe2);
648 } while (read_next_x(oenv,status,&t,natoms,x,box));
649 close_trj(status);
650 } else {
651 mat_x2=mat_x;
652 time2=time;
653 tel_mat2=tel_mat;
654 freq2=freq;
656 gmx_rmpbc_done(gpbc);
658 if (bMat || bBond) {
659 /* calculate RMS matrix */
660 fprintf(stderr,"\n");
661 if (bMat) {
662 fprintf(stderr,"Building %s matrix, %dx%d elements\n",
663 whatname[ewhat],tel_mat,tel_mat2);
664 snew(rmsd_mat,tel_mat);
666 if (bBond) {
667 fprintf(stderr,"Building bond angle matrix, %dx%d elements\n",
668 tel_mat,tel_mat2);
669 snew(bond_mat,tel_mat);
671 snew(axis,tel_mat);
672 snew(axis2,tel_mat2);
673 rmsd_max=0;
674 if (bFile2)
675 rmsd_min=1e10;
676 else
677 rmsd_min=0;
678 rmsd_avg=0;
679 bond_max=0;
680 bond_min=1e10;
681 for(j=0; j<tel_mat2; j++)
682 axis2[j]=time2[freq2*j];
683 if (bDelta) {
684 if (bDeltaLog) {
685 delta_scalex=8.0/log(2.0);
686 delta_xsize=(int)(log(tel_mat/2)*delta_scalex+0.5)+1;
688 else {
689 delta_xsize=tel_mat/2;
691 delta_scaley=1.0/delta_maxy;
692 snew(delta,delta_xsize);
693 for(j=0; j<delta_xsize; j++)
694 snew(delta[j],del_lev+1);
695 if (avl > 0) {
696 snew(rmsdav_mat,tel_mat);
697 for(j=0; j<tel_mat; j++)
698 snew(rmsdav_mat[j],tel_mat);
702 if (bFitAll)
703 snew(mat_x2_j,natoms);
704 for(i=0; i<tel_mat; i++) {
705 axis[i]=time[freq*i];
706 fprintf(stderr,"\r element %5d; time %5.2f ",i,axis[i]);
707 if (bMat) snew(rmsd_mat[i],tel_mat2);
708 if (bBond) snew(bond_mat[i],tel_mat2);
709 for(j=0; j<tel_mat2; j++) {
710 if (bFitAll) {
711 for (k=0;k<n_ind_m;k++)
712 copy_rvec(mat_x2[j][k],mat_x2_j[k]);
713 do_fit(n_ind_m,w_rls_m,mat_x[i],mat_x2_j);
714 } else
715 mat_x2_j=mat_x2[j];
716 if (bMat) {
717 if (bFile2 || (i<j)) {
718 rmsd_mat[i][j] =
719 calc_similar_ind(ewhat!=ewRMSD,irms[0],ind_rms_m,
720 w_rms_m,mat_x[i],mat_x2_j);
721 if (rmsd_mat[i][j] > rmsd_max) rmsd_max=rmsd_mat[i][j];
722 if (rmsd_mat[i][j] < rmsd_min) rmsd_min=rmsd_mat[i][j];
723 rmsd_avg += rmsd_mat[i][j];
724 } else
725 rmsd_mat[i][j]=rmsd_mat[j][i];
727 if (bBond) {
728 if (bFile2 || (i<=j)) {
729 ang=0.0;
730 for(m=0;m<ibond;m++) {
731 rvec_sub(mat_x[i][ind_bond1[m]],mat_x[i][ind_bond2[m]],vec1);
732 rvec_sub(mat_x2_j[ind_bond1[m]],mat_x2_j[ind_bond2[m]],vec2);
733 ang += acos(cos_angle(vec1,vec2));
735 bond_mat[i][j]=ang*180.0/(M_PI*ibond);
736 if (bond_mat[i][j] > bond_max) bond_max=bond_mat[i][j];
737 if (bond_mat[i][j] < bond_min) bond_min=bond_mat[i][j];
739 else
740 bond_mat[i][j]=bond_mat[j][i];
744 if (bFile2)
745 rmsd_avg /= tel_mat*tel_mat2;
746 else
747 rmsd_avg /= tel_mat*(tel_mat - 1)/2;
748 if (bMat && (avl > 0)) {
749 rmsd_max=0.0;
750 rmsd_min=0.0;
751 rmsd_avg=0.0;
752 for(j=0; j<tel_mat-1; j++) {
753 for(i=j+1; i<tel_mat; i++) {
754 av_tot=0;
755 weight_tot=0;
756 for (my=-avl; my<=avl; my++) {
757 if ((j+my>=0) && (j+my<tel_mat)) {
758 abs_my = abs(my);
759 for (mx=-avl; mx<=avl; mx++) {
760 if ((i+mx>=0) && (i+mx<tel_mat)) {
761 weight = (real)(avl+1-max(abs(mx),abs_my));
762 av_tot += weight*rmsd_mat[i+mx][j+my];
763 weight_tot+=weight;
768 rmsdav_mat[i][j] = av_tot/weight_tot;
769 rmsdav_mat[j][i] = rmsdav_mat[i][j];
770 if (rmsdav_mat[i][j] > rmsd_max) rmsd_max=rmsdav_mat[i][j];
773 rmsd_mat=rmsdav_mat;
776 if (bMat) {
777 fprintf(stderr,"\n%s: Min %f, Max %f, Avg %f\n",
778 whatname[ewhat],rmsd_min,rmsd_max,rmsd_avg);
779 rlo.r = 1; rlo.g = 1; rlo.b = 1;
780 rhi.r = 0; rhi.g = 0; rhi.b = 0;
781 if (rmsd_user_max != -1) rmsd_max=rmsd_user_max;
782 if (rmsd_user_min != -1) rmsd_min=rmsd_user_min;
783 if ((rmsd_user_max != -1) || (rmsd_user_min != -1))
784 fprintf(stderr,"Min and Max value set to resp. %f and %f\n",
785 rmsd_min,rmsd_max);
786 sprintf(buf,"%s %s matrix",gn_rms[0],whatname[ewhat]);
787 write_xpm(opt2FILE("-m",NFILE,fnm,"w"),0,buf,whatlabel[ewhat],
788 output_env_get_time_label(oenv),output_env_get_time_label(oenv),tel_mat,tel_mat2,
789 axis,axis2, rmsd_mat,rmsd_min,rmsd_max,rlo,rhi,&nlevels);
790 /* Print the distribution of RMSD values */
791 if (opt2bSet("-dist",NFILE,fnm))
792 low_rmsd_dist(opt2fn("-dist",NFILE,fnm),rmsd_max,tel_mat,rmsd_mat,oenv);
794 if (bDelta) {
795 snew(delta_tot,delta_xsize);
796 for(j=0; j<tel_mat-1; j++) {
797 for(i=j+1; i<tel_mat; i++) {
798 mx=i-j ;
799 if (mx < tel_mat/2) {
800 if (bDeltaLog)
801 mx=(int)(log(mx)*delta_scalex+0.5);
802 my=(int)(rmsd_mat[i][j]*delta_scaley*del_lev+0.5);
803 delta_tot[mx] += 1.0;
804 if ((rmsd_mat[i][j]>=0) && (rmsd_mat[i][j]<=delta_maxy))
805 delta[mx][my] += 1.0;
809 delta_max=0;
810 for(i=0; i<delta_xsize; i++) {
811 if (delta_tot[i] > 0.0) {
812 delta_tot[i]=1.0/delta_tot[i];
813 for(j=0; j<=del_lev; j++) {
814 delta[i][j] *= delta_tot[i];
815 if (delta[i][j] > delta_max)
816 delta_max=delta[i][j];
820 fprintf(stderr,"Maximum in delta matrix: %f\n",delta_max);
821 snew(del_xaxis,delta_xsize);
822 snew(del_yaxis,del_lev+1);
823 for (i=0; i<delta_xsize; i++)
824 del_xaxis[i]=axis[i]-axis[0];
825 for (i=0; i<del_lev+1; i++)
826 del_yaxis[i]=delta_maxy*i/del_lev;
827 sprintf(buf,"%s %s vs. delta t",gn_rms[0],whatname[ewhat]);
828 fp = ffopen("delta.xpm","w");
829 write_xpm(fp,0,buf,"density",output_env_get_time_label(oenv),whatlabel[ewhat],
830 delta_xsize,del_lev+1,del_xaxis,del_yaxis,
831 delta,0.0,delta_max,rlo,rhi,&nlevels);
832 ffclose(fp);
834 if (opt2bSet("-bin",NFILE,fnm)) {
835 /* NB: File must be binary if we use fwrite */
836 fp=ftp2FILE(efDAT,NFILE,fnm,"wb");
837 for(i=0;i<tel_mat;i++)
838 if(fwrite(rmsd_mat[i],sizeof(**rmsd_mat),tel_mat2,fp) != tel_mat2)
840 gmx_fatal(FARGS,"Error writing to output file");
842 ffclose(fp);
845 if (bBond) {
846 fprintf(stderr,"\nMin. angle: %f, Max. angle: %f\n",bond_min,bond_max);
847 if (bond_user_max != -1) bond_max=bond_user_max;
848 if (bond_user_min != -1) bond_min=bond_user_min;
849 if ((bond_user_max != -1) || (bond_user_min != -1))
850 fprintf(stderr,"Bond angle Min and Max set to:\n"
851 "Min. angle: %f, Max. angle: %f\n",bond_min,bond_max);
852 rlo.r = 1; rlo.g = 1; rlo.b = 1;
853 rhi.r = 0; rhi.g = 0; rhi.b = 0;
854 sprintf(buf,"%s av. bond angle deviation",gn_rms[0]);
855 write_xpm(opt2FILE("-bm",NFILE,fnm,"w"),0,buf,"degrees",
856 output_env_get_time_label(oenv),output_env_get_time_label(oenv),tel_mat,tel_mat2,
857 axis,axis2, bond_mat,bond_min,bond_max,rlo,rhi,&nlevels);
861 bAv=opt2bSet("-a",NFILE,fnm);
863 /* Write the RMSD's to file */
864 if (!bPrev)
865 sprintf(buf,"%s",whatxvgname[ewhat]);
866 else
867 sprintf(buf,"%s with frame %g %s ago",whatxvgname[ewhat],
868 time[prev*freq]-time[0], output_env_get_time_label(oenv));
869 fp=xvgropen(opt2fn("-o",NFILE,fnm),buf,output_env_get_xvgr_tlabel(oenv),
870 whatxvglabel[ewhat], oenv);
871 if (output_env_get_print_xvgr_codes(oenv))
872 fprintf(fp,"@ subtitle \"%s%s after %s%s%s\"\n",
873 (nrms==1)?"":"of " , gn_rms[0], fitgraphlabel[efit],
874 bFit ?" to ":"" , bFit?gn_fit:"");
875 if (nrms != 1)
876 xvgr_legend(fp,nrms,(const char**)gn_rms,oenv);
877 for(i=0; (i<teller); i++) {
878 if ( bSplit && i>0 &&
879 abs(time[bPrev ? freq*i : i]/output_env_get_time_factor(oenv))<1e-5 )
881 fprintf(fp,"&\n");
883 fprintf(fp,"%12.7f",time[bPrev ? freq*i : i]);
884 for(j=0; (j<nrms); j++) {
885 fprintf(fp," %12.7f",rls[j][i]);
886 if (bAv)
887 rlstot+=rls[j][i];
889 fprintf(fp,"\n");
891 ffclose(fp);
893 if (bMirror) {
894 /* Write the mirror RMSD's to file */
895 sprintf(buf,"%s with Mirror",whatxvgname[ewhat]);
896 sprintf(buf2,"Mirror %s",whatxvglabel[ewhat]);
897 fp=xvgropen(opt2fn("-mir",NFILE,fnm), buf, output_env_get_xvgr_tlabel(oenv),
898 buf2,oenv);
899 if (nrms == 1) {
900 if (output_env_get_print_xvgr_codes(oenv))
901 fprintf(fp,"@ subtitle \"of %s after lsq fit to mirror of %s\"\n",
902 gn_rms[0],gn_fit);
904 else {
905 if (output_env_get_print_xvgr_codes(oenv))
906 fprintf(fp,"@ subtitle \"after lsq fit to mirror %s\"\n",gn_fit);
907 xvgr_legend(fp,nrms,(const char**)gn_rms,oenv);
909 for(i=0; (i<teller); i++) {
910 if ( bSplit && i>0 && abs(time[i])<1e-5 )
911 fprintf(fp,"&\n");
912 fprintf(fp,"%12.7f",time[i]);
913 for(j=0; (j<nrms); j++)
914 fprintf(fp," %12.7f",rlsm[j][i]);
915 fprintf(fp,"\n");
917 ffclose(fp);
920 if (bAv) {
921 sprintf(buf,"Average %s",whatxvgname[ewhat]);
922 sprintf(buf2,"Average %s",whatxvglabel[ewhat]);
923 fp = xvgropen(opt2fn("-a",NFILE,fnm), buf, "Residue", buf2,oenv);
924 for(j=0; (j<nrms); j++)
925 fprintf(fp,"%10d %10g\n",j,rlstot/teller);
926 ffclose(fp);
929 if (bNorm) {
930 fp = xvgropen("aver.xvg",gn_rms[0],"Residue",whatxvglabel[ewhat],oenv);
931 for(j=0; (j<irms[0]); j++)
932 fprintf(fp,"%10d %10g\n",j,rlsnorm[j]/teller);
933 ffclose(fp);
935 do_view(oenv,opt2fn_null("-a",NFILE,fnm),"-graphtype bar");
936 do_view(oenv,opt2fn("-o",NFILE,fnm),NULL);
937 do_view(oenv,opt2fn_null("-mir",NFILE,fnm),NULL);
938 do_view(oenv,opt2fn_null("-m",NFILE,fnm),NULL);
939 do_view(oenv,opt2fn_null("-bm",NFILE,fnm),NULL);
940 do_view(oenv,opt2fn_null("-dist",NFILE,fnm),NULL);
942 thanx(stderr);
944 return 0;