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
45 #include "gmx_fatal.h"
64 static void calc_entropy_qh(FILE *fp
,int n
,real eigval
[],real temp
,int nskip
)
70 hbar
= PLANCK1
/(2*M_PI
);
71 for(i
=0; (i
<n
-nskip
); i
++) {
73 lambda
= eigval
[i
]*AMU
;
74 w
= sqrt(BOLTZMANN
*temp
/lambda
)/NANO
;
75 hwkT
= (hbar
*w
)/(BOLTZMANN
*temp
);
76 dS
= (hwkT
/(exp(hwkT
) - 1) - log(1-exp(-hwkT
)));
79 fprintf(debug
,"i = %5d w = %10g lam = %10g hwkT = %10g dS = %10g\n",
83 fprintf(stderr
,"eigval[%d] = %g\n",i
,eigval
[i
]);
87 fprintf(fp
,"The Entropy due to the Quasi Harmonic approximation is %g J/mol K\n",
91 static void calc_entropy_schlitter(FILE *fp
,int n
,int nskip
,
92 real
*eigval
,real temp
)
98 double hbar
,kt
,kteh
,S
;
100 hbar
= PLANCK1
/(2*M_PI
);
102 kteh
= kt
*exp(2.0)/(hbar
*hbar
)*AMU
*sqr(NANO
);
104 fprintf(debug
,"n = %d, nskip = %d kteh = %g\n",n
,nskip
,kteh
);
107 for(i
=0; (i
<n
-nskip
); i
++) {
108 dd
= 1+kteh
*eigval
[i
];
113 fprintf(fp
,"The Entropy due to the Schlitter formula is %g J/mol K\n",S
);
116 const char *proj_unit
;
118 static real
tick_spacing(real range
,int minticks
)
122 sp
= 0.2*exp(log(10)*ceil(log(range
)/log(10)));
123 while (range
/sp
< minticks
-1)
129 static void write_xvgr_graphs(const char *file
, int ngraphs
, int nsetspergraph
,
130 const char *title
, const char *subtitle
,
131 const char *xlabel
, const char **ylabel
,
132 int n
, real
*x
, real
**y
, real
***sy
,
133 real scale_x
, bool bZero
, bool bSplit
,
134 const output_env_t oenv
)
138 real min
,max
,xsp
,ysp
;
140 out
=ffopen(file
,"w");
141 if (!use_xmgr() && get_print_xvgr_codes(oenv
))
142 fprintf(out
,"@ autoscale onread none\n");
143 for(g
=0; g
<ngraphs
; g
++) {
148 if (y
[g
][i
]<min
) min
=y
[g
][i
];
149 if (y
[g
][i
]>max
) max
=y
[g
][i
];
154 for(s
=0; s
<nsetspergraph
; s
++)
156 if (sy
[g
][s
][i
]<min
) min
=sy
[g
][s
][i
];
157 if (sy
[g
][s
][i
]>max
) max
=sy
[g
][s
][i
];
163 min
=min
-0.1*(max
-min
);
164 max
=max
+0.1*(max
-min
);
165 xsp
=tick_spacing((x
[n
-1]-x
[0])*scale_x
,4);
166 ysp
=tick_spacing(max
-min
,3);
167 if (get_print_xvgr_codes(oenv
)) {
168 fprintf(out
,"@ with g%d\n@ g%d on\n",g
,g
);
170 fprintf(out
,"@ title \"%s\"\n",title
);
172 fprintf(out
,"@ subtitle \"%s\"\n",subtitle
);
175 fprintf(out
,"@ xaxis label \"%s\"\n",xlabel
);
177 fprintf(out
,"@ xaxis ticklabel off\n");
178 fprintf(out
,"@ world xmin %g\n",x
[0]*scale_x
);
179 fprintf(out
,"@ world xmax %g\n",x
[n
-1]*scale_x
);
180 fprintf(out
,"@ world ymin %g\n",min
);
181 fprintf(out
,"@ world ymax %g\n",max
);
182 fprintf(out
,"@ view xmin 0.15\n");
183 fprintf(out
,"@ view xmax 0.85\n");
184 fprintf(out
,"@ view ymin %g\n",0.15+(ngraphs
-1-g
)*0.7/ngraphs
);
185 fprintf(out
,"@ view ymax %g\n",0.15+(ngraphs
-g
)*0.7/ngraphs
);
186 fprintf(out
,"@ yaxis label \"%s\"\n",ylabel
[g
]);
187 fprintf(out
,"@ xaxis tick major %g\n",xsp
);
188 fprintf(out
,"@ xaxis tick minor %g\n",xsp
/2);
189 fprintf(out
,"@ xaxis ticklabel start type spec\n");
190 fprintf(out
,"@ xaxis ticklabel start %g\n",ceil(min
/xsp
)*xsp
);
191 fprintf(out
,"@ yaxis tick major %g\n",ysp
);
192 fprintf(out
,"@ yaxis tick minor %g\n",ysp
/2);
193 fprintf(out
,"@ yaxis ticklabel start type spec\n");
194 fprintf(out
,"@ yaxis ticklabel start %g\n",ceil(min
/ysp
)*ysp
);
195 if ((min
<0) && (max
>0)) {
196 fprintf(out
,"@ zeroxaxis bar on\n");
197 fprintf(out
,"@ zeroxaxis bar linestyle 3\n");
200 for(s
=0; s
<nsetspergraph
; s
++) {
202 if ( bSplit
&& i
>0 && abs(x
[i
])<1e-5 )
204 if (get_print_xvgr_codes(oenv
))
207 fprintf(out
,"%10.4f %10.5f\n",
208 x
[i
]*scale_x
,y
? y
[g
][i
] : sy
[g
][s
][i
]);
210 if (get_print_xvgr_codes(oenv
))
218 compare(int natoms
,int n1
,rvec
**eigvec1
,int n2
,rvec
**eigvec2
,
219 real
*eigval1
, int neig1
, real
*eigval2
, int neig2
)
223 double sum1
,sum2
,trace1
,trace2
,sab
,samsb2
,tmp
,ip
;
227 n
= min(n
,min(neig1
,neig2
));
228 fprintf(stdout
,"Will compare the covariance matrices using %d dimensions\n",n
);
236 eigval1
[i
] = sqrt(eigval1
[i
]);
239 for(i
=n
; i
<neig1
; i
++)
240 trace1
+= eigval1
[i
];
247 eigval2
[i
] = sqrt(eigval2
[i
]);
250 for(i
=n
; i
<neig2
; i
++)
251 trace2
+= eigval2
[i
];
253 fprintf(stdout
,"Trace of the two matrices: %g and %g\n",sum1
,sum2
);
254 if (neig1
!=n
|| neig2
!=n
)
255 fprintf(stdout
,"this is %d%% and %d%% of the total trace\n",
256 (int)(100*sum1
/trace1
+0.5),(int)(100*sum2
/trace2
+0.5));
257 fprintf(stdout
,"Square root of the traces: %g and %g\n",
258 sqrt(sum1
),sqrt(sum2
));
267 for(k
=0; k
<natoms
; k
++)
268 ip
+= iprod(eigvec1
[i
][k
],eigvec2
[j
][k
]);
269 tmp
+= eigval2
[j
]*ip
*ip
;
271 sab
+= eigval1
[i
]*tmp
;
274 samsb2
= sum1
+sum2
-2*sab
;
278 fprintf(stdout
,"The overlap of the covariance matrices:\n");
279 fprintf(stdout
," normalized: %.3f\n",1-sqrt(samsb2
/(sum1
+sum2
)));
280 tmp
= 1-sab
/sqrt(sum1
*sum2
);
283 fprintf(stdout
," shape: %.3f\n",1-sqrt(tmp
));
287 static void inprod_matrix(const char *matfile
,int natoms
,
288 int nvec1
,int *eignr1
,rvec
**eigvec1
,
289 int nvec2
,int *eignr2
,rvec
**eigvec2
,
290 bool bSelect
,int noutvec
,int *outvec
)
294 int i
,x1
,y1
,x
,y
,nlevels
;
296 real inp
,*t_x
,*t_y
,max
;
303 for(y1
=0; y1
<nx
; y1
++)
304 if (outvec
[y1
] < nvec2
) {
305 t_y
[ny
] = eignr2
[outvec
[y1
]]+1;
312 t_y
[y
] = eignr2
[y
]+1;
315 fprintf(stderr
,"Calculating inner-product matrix of %dx%d eigenvectors\n",
321 for(x1
=0; x1
<nx
; x1
++) {
327 t_x
[x1
] = eignr1
[x
]+1;
328 fprintf(stderr
," %d",eignr1
[x
]+1);
329 for(y1
=0; y1
<ny
; y1
++) {
332 while (outvec
[y1
] >= nvec2
)
337 for(i
=0; i
<natoms
; i
++)
338 inp
+= iprod(eigvec1
[x
][i
],eigvec2
[y
][i
]);
339 mat
[x1
][y1
] = fabs(inp
);
344 fprintf(stderr
,"\n");
345 rlo
.r
= 1; rlo
.g
= 1; rlo
.b
= 1;
346 rhi
.r
= 0; rhi
.g
= 0; rhi
.b
= 0;
348 out
= ffopen(matfile
,"w");
349 write_xpm(out
,0,"Eigenvector inner-products","in.prod.","run 1","run 2",
350 nx
,ny
,t_x
,t_y
,mat
,0.0,max
,rlo
,rhi
,&nlevels
);
354 static void overlap(const char *outfile
,int natoms
,
356 int nvec2
,int *eignr2
,rvec
**eigvec2
,
357 int noutvec
,int *outvec
,
358 const output_env_t oenv
)
364 fprintf(stderr
,"Calculating overlap between eigenvectors of set 2 with eigenvectors\n");
365 for(i
=0; i
<noutvec
; i
++)
366 fprintf(stderr
,"%d ",outvec
[i
]+1);
367 fprintf(stderr
,"\n");
369 out
=xvgropen(outfile
,"Subspace overlap",
370 "Eigenvectors of trajectory 2","Overlap",oenv
);
371 fprintf(out
,"@ subtitle \"using %d eigenvectors of trajectory 1\"\n",
374 for(x
=0; x
<nvec2
; x
++) {
375 for(v
=0; v
<noutvec
; v
++) {
378 for(i
=0; i
<natoms
; i
++)
379 inp
+=iprod(eigvec1
[vec
][i
],eigvec2
[x
][i
]);
382 fprintf(out
,"%5d %5.3f\n",eignr2
[x
]+1,overlap
/noutvec
);
388 static void project(const char *trajfile
,t_topology
*top
,int ePBC
,
389 matrix topbox
, rvec
*xtop
,
390 const char *projfile
,const char *twodplotfile
,
391 const char *threedplotfile
, const char *filterfile
,int skip
,
392 const char *extremefile
,bool bExtrAll
,real extreme
,
393 int nextr
, t_atoms
*atoms
,int natoms
,atom_id
*index
,
394 bool bFit
,rvec
*xref
,int nfit
,atom_id
*ifit
,real
*w_rls
,
395 real
*sqrtm
,rvec
*xav
,
396 int *eignr
,rvec
**eigvec
,
397 int noutvec
,int *outvec
, bool bSplit
,
398 const output_env_t oenv
)
401 int status
,out
=0,nat
,i
,j
,d
,v
,vec
,nfr
,nframes
=0,snew_size
,frame
;
402 int noutvec_extr
,*imin
,*imax
;
406 real t
,inp
,**inprod
=NULL
,min
=0,max
=0;
407 char str
[STRLEN
],str2
[STRLEN
],**ylabel
,*c
;
413 noutvec_extr
=noutvec
;
419 snew(inprod
,noutvec
+1);
422 fprintf(stderr
,"Writing a filtered trajectory to %s using eigenvectors\n",
424 for(i
=0; i
<noutvec
; i
++)
425 fprintf(stderr
,"%d ",outvec
[i
]+1);
426 fprintf(stderr
,"\n");
427 out
=open_trx(filterfile
,"w");
432 nat
=read_first_x(oenv
,&status
,trajfile
,&t
,&xread
,box
);
434 gmx_fatal(FARGS
,"the number of atoms in your trajectory (%d) is larger than the number of atoms in your structure file (%d)",nat
,atoms
->nr
);
439 if (nfr
% skip
== 0) {
441 rm_pbc(&(top
->idef
),ePBC
,nat
,box
,xread
,xread
);
442 if (nframes
>=snew_size
) {
444 for(i
=0; i
<noutvec
+1; i
++)
445 srenew(inprod
[i
],snew_size
);
447 inprod
[noutvec
][nframes
]=t
;
448 /* calculate x: a fitted struture of the selected atoms */
449 if (bFit
&& (xref
==NULL
)) {
450 reset_x(nfit
,ifit
,nat
,NULL
,xread
,w_rls
);
451 do_fit(nat
,w_rls
,xtop
,xread
);
453 for (i
=0; i
<natoms
; i
++)
454 copy_rvec(xread
[index
[i
]],x
[i
]);
456 reset_x(natoms
,all_at
,natoms
,NULL
,x
,w_rls
);
457 do_fit(natoms
,w_rls
,xref
,x
);
460 for(v
=0; v
<noutvec
; v
++) {
462 /* calculate (mass-weighted) projection */
464 for (i
=0; i
<natoms
; i
++) {
465 inp
+=(eigvec
[vec
][i
][0]*(x
[i
][0]-xav
[i
][0])+
466 eigvec
[vec
][i
][1]*(x
[i
][1]-xav
[i
][1])+
467 eigvec
[vec
][i
][2]*(x
[i
][2]-xav
[i
][2]))*sqrtm
[i
];
469 inprod
[v
][nframes
]=inp
;
472 for(i
=0; i
<natoms
; i
++)
473 for(d
=0; d
<DIM
; d
++) {
474 /* misuse xread for output */
475 xread
[index
[i
]][d
] = xav
[i
][d
];
476 for(v
=0; v
<noutvec
; v
++)
477 xread
[index
[i
]][d
] +=
478 inprod
[v
][nframes
]*eigvec
[outvec
[v
]][i
][d
]/sqrtm
[i
];
480 write_trx(out
,natoms
,index
,atoms
,0,t
,box
,xread
,NULL
,NULL
);
485 } while (read_next_x(oenv
,status
,&t
,nat
,xread
,box
));
492 snew(xread
,atoms
->nr
);
496 snew(ylabel
,noutvec
);
497 for(v
=0; v
<noutvec
; v
++) {
498 sprintf(str
,"vec %d",eignr
[outvec
[v
]]+1);
499 ylabel
[v
]=strdup(str
);
501 sprintf(str
,"projection on eigenvectors (%s)",proj_unit
);
502 write_xvgr_graphs(projfile
, noutvec
, 1, str
, NULL
, get_xvgr_tlabel(oenv
),
503 (const char **)ylabel
,
504 nframes
, inprod
[noutvec
], inprod
, NULL
,
505 get_time_factor(oenv
), FALSE
, bSplit
,oenv
);
509 sprintf(str
,"projection on eigenvector %d (%s)",
510 eignr
[outvec
[0]]+1,proj_unit
);
511 sprintf(str2
,"projection on eigenvector %d (%s)",
512 eignr
[outvec
[noutvec
-1]]+1,proj_unit
);
513 xvgrout
=xvgropen(twodplotfile
,"2D projection of trajectory",str
,str2
,
515 for(i
=0; i
<nframes
; i
++) {
516 if ( bSplit
&& i
>0 && abs(inprod
[noutvec
][i
])<1e-5 )
517 fprintf(xvgrout
,"&\n");
518 fprintf(xvgrout
,"%10.5f %10.5f\n",inprod
[0][i
],inprod
[noutvec
-1][i
]);
523 if (threedplotfile
) {
528 char *resnm
,*atnm
, pdbform
[STRLEN
];
533 gmx_fatal(FARGS
,"You have selected less than 3 eigenvectors");
536 bPDB
= fn2ftp(threedplotfile
)==efPDB
;
538 box
[XX
][XX
] = box
[YY
][YY
] = box
[ZZ
][ZZ
] = 1;
540 b4D
= bPDB
&& (noutvec
>= 4);
542 fprintf(stderr
, "You have selected four or more eigenvectors:\n"
543 "fourth eigenvector will be plotted "
544 "in bfactor field of pdb file\n");
545 sprintf(str
,"4D proj. of traj. on eigenv. %d, %d, %d and %d",
546 eignr
[outvec
[0]]+1,eignr
[outvec
[1]]+1,
547 eignr
[outvec
[2]]+1,eignr
[outvec
[3]]+1);
549 sprintf(str
,"3D proj. of traj. on eigenv. %d, %d and %d",
550 eignr
[outvec
[0]]+1,eignr
[outvec
[1]]+1,eignr
[outvec
[2]]+1);
552 init_t_atoms(&atoms
,nframes
,FALSE
);
559 fact
=10000.0/nframes
;
563 for(i
=0; i
<nframes
; i
++) {
564 atoms
.atomname
[i
] = &atnm
;
565 atoms
.atom
[i
].resind
= i
;
566 atoms
.resinfo
[i
].name
= &resnm
;
567 atoms
.resinfo
[i
].nr
= ceil(i
*fact
);
568 atoms
.resinfo
[i
].ic
= ' ';
569 x
[i
][XX
]=inprod
[0][i
];
570 x
[i
][YY
]=inprod
[1][i
];
571 x
[i
][ZZ
]=inprod
[2][i
];
575 if ( ( b4D
|| bSplit
) && bPDB
) {
576 strcpy(pdbform
,pdbformat
);
577 strcat(pdbform
,"%8.4f%8.4f\n");
579 out
=ffopen(threedplotfile
,"w");
580 fprintf(out
,"HEADER %s\n",str
);
582 fprintf(out
,"REMARK %s\n","fourth dimension plotted as B-factor");
584 for(i
=0; i
<atoms
.nr
; i
++) {
585 if ( j
>0 && bSplit
&& abs(inprod
[noutvec
][i
])<1e-5 ) {
586 fprintf(out
,"TER\n");
589 fprintf(out
,pdbform
,"ATOM",i
+1,"C","PRJ",' ',j
+1,
590 PR_VEC(10*x
[i
]), 1.0, 10*b
[i
]);
592 fprintf(out
,"CONECT%5d%5d\n", i
, i
+1);
595 fprintf(out
,"TER\n");
598 write_sto_conf(threedplotfile
,str
,&atoms
,x
,NULL
,ePBC
,box
);
599 free_t_atoms(&atoms
,FALSE
);
604 fprintf(stderr
,"%11s %17s %17s\n","eigenvector","Minimum","Maximum");
606 "%11s %10s %10s %10s %10s\n","","value","time","value","time");
607 snew(imin
,noutvec_extr
);
608 snew(imax
,noutvec_extr
);
609 for(v
=0; v
<noutvec_extr
; v
++) {
610 for(i
=0; i
<nframes
; i
++) {
611 if (inprod
[v
][i
]<inprod
[v
][imin
[v
]])
613 if (inprod
[v
][i
]>inprod
[v
][imax
[v
]])
616 min
=inprod
[v
][imin
[v
]];
617 max
=inprod
[v
][imax
[v
]];
618 fprintf(stderr
,"%7d %10.6f %10.1f %10.6f %10.1f\n",
620 min
,inprod
[noutvec
][imin
[v
]],max
,inprod
[noutvec
][imax
[v
]]);
627 /* build format string for filename: */
628 strcpy(str
,extremefile
);/* copy filename */
629 c
=strrchr(str
,'.'); /* find where extention begins */
630 strcpy(str2
,c
); /* get extention */
631 sprintf(c
,"%%d%s",str2
); /* append '%s' and extention to filename */
632 for(v
=0; v
<noutvec_extr
; v
++) {
633 /* make filename using format string */
635 strcpy(str2
,extremefile
);
637 sprintf(str2
,str
,eignr
[outvec
[v
]]+1);
638 fprintf(stderr
,"Writing %d frames along eigenvector %d to %s\n",
639 nextr
,outvec
[v
]+1,str2
);
640 out
=open_trx(str2
,"w");
641 for(frame
=0; frame
<nextr
; frame
++) {
642 if ((extreme
==0) && (nextr
<=3))
643 for(i
=0; i
<natoms
; i
++) {
644 atoms
->resinfo
[atoms
->atom
[index
[i
]].resind
].chain
= 'A' + frame
;
646 for(i
=0; i
<natoms
; i
++)
649 (xav
[i
][d
] + (min
*(nextr
-frame
-1)+max
*frame
)/(nextr
-1)
650 *eigvec
[outvec
[v
]][i
][d
]/sqrtm
[i
]);
651 write_trx(out
,natoms
,index
,atoms
,0,frame
,topbox
,xread
,NULL
,NULL
);
656 fprintf(stderr
,"\n");
659 static void components(const char *outfile
,int natoms
,
660 int *eignr
,rvec
**eigvec
,
661 int noutvec
,int *outvec
,
662 const output_env_t oenv
)
666 char str
[STRLEN
],**ylabel
;
668 fprintf(stderr
,"Writing eigenvector components to %s\n",outfile
);
670 snew(ylabel
,noutvec
);
673 for(i
=0; i
<natoms
; i
++)
675 for(g
=0; g
<noutvec
; g
++) {
677 sprintf(str
,"vec %d",eignr
[v
]+1);
678 ylabel
[g
]=strdup(str
);
681 snew(y
[g
][s
],natoms
);
683 for(i
=0; i
<natoms
; i
++) {
684 y
[g
][0][i
] = norm(eigvec
[v
][i
]);
686 y
[g
][s
+1][i
] = eigvec
[v
][i
][s
];
689 write_xvgr_graphs(outfile
,noutvec
,4,"Eigenvector components",
690 "black: total, red: x, green: y, blue: z",
691 "Atom number",(const char **)ylabel
,
692 natoms
,x
,NULL
,y
,1,FALSE
,FALSE
,oenv
);
693 fprintf(stderr
,"\n");
696 static void rmsf(const char *outfile
,int natoms
,real
*sqrtm
,
697 int *eignr
,rvec
**eigvec
,
698 int noutvec
,int *outvec
,
699 real
*eigval
, int neig
,
700 const output_env_t oenv
)
704 char str
[STRLEN
],**ylabel
;
706 for(i
=0; i
<neig
; i
++)
710 fprintf(stderr
,"Writing rmsf to %s\n",outfile
);
712 snew(ylabel
,noutvec
);
715 for(i
=0; i
<natoms
; i
++)
717 for(g
=0; g
<noutvec
; g
++) {
719 if (eignr
[v
] >= neig
)
720 gmx_fatal(FARGS
,"Selected vector %d is larger than the number of eigenvalues (%d)",eignr
[v
]+1,neig
);
721 sprintf(str
,"vec %d",eignr
[v
]+1);
722 ylabel
[g
]=strdup(str
);
724 for(i
=0; i
<natoms
; i
++)
725 y
[g
][i
] = sqrt(eigval
[eignr
[v
]]*norm2(eigvec
[v
][i
]))/sqrtm
[i
];
727 write_xvgr_graphs(outfile
,noutvec
,1,"RMS fluctuation (nm) ",NULL
,
728 "Atom number",(const char **)ylabel
,
729 natoms
,x
,y
,NULL
,1,TRUE
,FALSE
,oenv
);
730 fprintf(stderr
,"\n");
733 int gmx_anaeig(int argc
,char *argv
[])
735 static const char *desc
[] = {
736 "[TT]g_anaeig[tt] analyzes eigenvectors. The eigenvectors can be of a",
737 "covariance matrix ([TT]g_covar[tt]) or of a Normal Modes anaysis",
738 "([TT]g_nmeig[tt]).[PAR]",
740 "When a trajectory is projected on eigenvectors, all structures are",
741 "fitted to the structure in the eigenvector file, if present, otherwise",
742 "to the structure in the structure file. When no run input file is",
743 "supplied, periodicity will not be taken into account. Most analyses",
744 "are performed on eigenvectors [TT]-first[tt] to [TT]-last[tt], but when",
745 "[TT]-first[tt] is set to -1 you will be prompted for a selection.[PAR]",
747 "[TT]-comp[tt]: plot the vector components per atom of eigenvectors",
748 "[TT]-first[tt] to [TT]-last[tt].[PAR]",
750 "[TT]-rmsf[tt]: plot the RMS fluctuation per atom of eigenvectors",
751 "[TT]-first[tt] to [TT]-last[tt] (requires [TT]-eig[tt]).[PAR]",
753 "[TT]-proj[tt]: calculate projections of a trajectory on eigenvectors",
754 "[TT]-first[tt] to [TT]-last[tt].",
755 "The projections of a trajectory on the eigenvectors of its",
756 "covariance matrix are called principal components (pc's).",
757 "It is often useful to check the cosine content the pc's,",
758 "since the pc's of random diffusion are cosines with the number",
759 "of periods equal to half the pc index.",
760 "The cosine content of the pc's can be calculated with the program",
761 "[TT]g_analyze[tt].[PAR]",
763 "[TT]-2d[tt]: calculate a 2d projection of a trajectory on eigenvectors",
764 "[TT]-first[tt] and [TT]-last[tt].[PAR]",
766 "[TT]-3d[tt]: calculate a 3d projection of a trajectory on the first",
767 "three selected eigenvectors.[PAR]",
769 "[TT]-filt[tt]: filter the trajectory to show only the motion along",
770 "eigenvectors [TT]-first[tt] to [TT]-last[tt].[PAR]",
772 "[TT]-extr[tt]: calculate the two extreme projections along a trajectory",
773 "on the average structure and interpolate [TT]-nframes[tt] frames",
774 "between them, or set your own extremes with [TT]-max[tt]. The",
775 "eigenvector [TT]-first[tt] will be written unless [TT]-first[tt] and",
776 "[TT]-last[tt] have been set explicitly, in which case all eigenvectors",
777 "will be written to separate files. Chain identifiers will be added",
778 "when writing a [TT].pdb[tt] file with two or three structures (you",
779 "can use [TT]rasmol -nmrpdb[tt] to view such a pdb file).[PAR]",
781 " Overlap calculations between covariance analysis:[BR]",
782 " NOTE: the analysis should use the same fitting structure[PAR]",
784 "[TT]-over[tt]: calculate the subspace overlap of the eigenvectors in",
785 "file [TT]-v2[tt] with eigenvectors [TT]-first[tt] to [TT]-last[tt]",
786 "in file [TT]-v[tt].[PAR]",
788 "[TT]-inpr[tt]: calculate a matrix of inner-products between",
789 "eigenvectors in files [TT]-v[tt] and [TT]-v2[tt]. All eigenvectors",
790 "of both files will be used unless [TT]-first[tt] and [TT]-last[tt]",
791 "have been set explicitly.[PAR]",
793 "When [TT]-v[tt], [TT]-eig[tt], [TT]-v2[tt] and [TT]-eig2[tt] are given,",
794 "a single number for the overlap between the covariance matrices is",
795 "generated. The formulas are:[BR]",
796 " difference = sqrt(tr((sqrt(M1) - sqrt(M2))^2))[BR]",
797 "normalized overlap = 1 - difference/sqrt(tr(M1) + tr(M2))[BR]",
798 " shape overlap = 1 - sqrt(tr((sqrt(M1/tr(M1)) - sqrt(M2/tr(M2)))^2))[BR]",
799 "where M1 and M2 are the two covariance matrices and tr is the trace",
800 "of a matrix. The numbers are proportional to the overlap of the square",
801 "root of the fluctuations. The normalized overlap is the most useful",
802 "number, it is 1 for identical matrices and 0 when the sampled",
803 "subspaces are orthogonal.[PAR]",
804 "When the [TT]-entropy[tt] flag is given an entropy estimate will be",
805 "computed based on the Quasiharmonic approach and based on",
806 "Schlitter's formula."
808 static int first
=1,last
=8,skip
=1,nextr
=2,nskip
=6;
809 static real max
=0.0,temp
=298.15;
810 static bool bSplit
=FALSE
,bEntropy
=FALSE
;
812 { "-first", FALSE
, etINT
, {&first
},
813 "First eigenvector for analysis (-1 is select)" },
814 { "-last", FALSE
, etINT
, {&last
},
815 "Last eigenvector for analysis (-1 is till the last)" },
816 { "-skip", FALSE
, etINT
, {&skip
},
817 "Only analyse every nr-th frame" },
818 { "-max", FALSE
, etREAL
, {&max
},
819 "Maximum for projection of the eigenvector on the average structure, "
820 "max=0 gives the extremes" },
821 { "-nframes", FALSE
, etINT
, {&nextr
},
822 "Number of frames for the extremes output" },
823 { "-split", FALSE
, etBOOL
, {&bSplit
},
824 "Split eigenvector projections where time is zero" },
825 { "-entropy", FALSE
, etBOOL
, {&bEntropy
},
826 "Compute entropy according to the Quasiharmonic formula or Schlitter's method." },
827 { "-temp", FALSE
, etREAL
, {&temp
},
828 "Temperature for entropy calculations" },
829 { "-nevskip", FALSE
, etINT
, {&nskip
},
830 "Number of eigenvalues to skip when computing the entropy due to the quasi harmonic approximation. When you do a rotational and/or translational fit prior to the covariance analysis, you get 3 or 6 eigenvalues that are very close to zero, and which should not be taken into account when computing the entropy." }
832 #define NPA asize(pa)
839 rvec
*xtop
,*xref1
,*xref2
;
840 bool bDMR1
,bDMA1
,bDMR2
,bDMA2
;
841 int nvec1
,nvec2
,*eignr1
=NULL
,*eignr2
=NULL
;
842 rvec
*x
,*xread
,*xav1
,*xav2
,**eigvec1
=NULL
,**eigvec2
=NULL
;
844 real xid
,totmass
,*sqrtm
,*w_rls
,t
,lambda
;
847 const char *indexfile
;
850 int nout
,*iout
,noutvec
,*outvec
,nfit
;
851 atom_id
*index
,*ifit
;
852 const char *VecFile
,*Vec2File
,*topfile
;
853 const char *EigFile
,*Eig2File
;
854 const char *CompFile
,*RmsfFile
,*ProjOnVecFile
;
855 const char *TwoDPlotFile
,*ThreeDPlotFile
;
856 const char *FilterFile
,*ExtremeFile
;
857 const char *OverlapFile
,*InpMatFile
;
858 bool bFit1
,bFit2
,bM
,bIndex
,bTPS
,bTop
,bVec2
,bProj
;
859 bool bFirstToLast
,bFirstLastSet
,bTraj
,bCompare
,bPDB3D
;
860 real
*eigval1
=NULL
,*eigval2
=NULL
;
866 { efTRN
, "-v", "eigenvec", ffREAD
},
867 { efTRN
, "-v2", "eigenvec2", ffOPTRD
},
868 { efTRX
, "-f", NULL
, ffOPTRD
},
869 { efTPS
, NULL
, NULL
, ffOPTRD
},
870 { efNDX
, NULL
, NULL
, ffOPTRD
},
871 { efXVG
, "-eig", "eigenval", ffOPTRD
},
872 { efXVG
, "-eig2", "eigenval2", ffOPTRD
},
873 { efXVG
, "-comp", "eigcomp", ffOPTWR
},
874 { efXVG
, "-rmsf", "eigrmsf", ffOPTWR
},
875 { efXVG
, "-proj", "proj", ffOPTWR
},
876 { efXVG
, "-2d", "2dproj", ffOPTWR
},
877 { efSTO
, "-3d", "3dproj.pdb", ffOPTWR
},
878 { efTRX
, "-filt", "filtered", ffOPTWR
},
879 { efTRX
, "-extr", "extreme.pdb", ffOPTWR
},
880 { efXVG
, "-over", "overlap", ffOPTWR
},
881 { efXPM
, "-inpr", "inprod", ffOPTWR
}
883 #define NFILE asize(fnm)
885 CopyRight(stderr
,argv
[0]);
886 parse_common_args(&argc
,argv
,
887 PCA_CAN_TIME
| PCA_TIME_UNIT
| PCA_CAN_VIEW
| PCA_BE_NICE
,
888 NFILE
,fnm
,NPA
,pa
,asize(desc
),desc
,0,NULL
,&oenv
);
890 indexfile
=ftp2fn_null(efNDX
,NFILE
,fnm
);
892 VecFile
= opt2fn("-v",NFILE
,fnm
);
893 Vec2File
= opt2fn_null("-v2",NFILE
,fnm
);
894 topfile
= ftp2fn(efTPS
,NFILE
,fnm
);
895 EigFile
= opt2fn_null("-eig",NFILE
,fnm
);
896 Eig2File
= opt2fn_null("-eig2",NFILE
,fnm
);
897 CompFile
= opt2fn_null("-comp",NFILE
,fnm
);
898 RmsfFile
= opt2fn_null("-rmsf",NFILE
,fnm
);
899 ProjOnVecFile
= opt2fn_null("-proj",NFILE
,fnm
);
900 TwoDPlotFile
= opt2fn_null("-2d",NFILE
,fnm
);
901 ThreeDPlotFile
= opt2fn_null("-3d",NFILE
,fnm
);
902 FilterFile
= opt2fn_null("-filt",NFILE
,fnm
);
903 ExtremeFile
= opt2fn_null("-extr",NFILE
,fnm
);
904 OverlapFile
= opt2fn_null("-over",NFILE
,fnm
);
905 InpMatFile
= ftp2fn_null(efXPM
,NFILE
,fnm
);
907 bTop
= fn2bTPX(topfile
);
908 bProj
= ProjOnVecFile
|| TwoDPlotFile
|| ThreeDPlotFile
909 || FilterFile
|| ExtremeFile
;
911 opt2parg_bSet("-first",NPA
,pa
) && opt2parg_bSet("-last",NPA
,pa
);
912 bFirstToLast
= CompFile
|| RmsfFile
|| ProjOnVecFile
|| FilterFile
||
913 OverlapFile
|| ((ExtremeFile
|| InpMatFile
) && bFirstLastSet
);
914 bVec2
= Vec2File
|| OverlapFile
|| InpMatFile
;
915 bM
= RmsfFile
|| bProj
;
916 bTraj
= ProjOnVecFile
|| FilterFile
|| (ExtremeFile
&& (max
==0))
917 || TwoDPlotFile
|| ThreeDPlotFile
;
918 bIndex
= bM
|| bProj
;
919 bTPS
= ftp2bSet(efTPS
,NFILE
,fnm
) || bM
|| bTraj
||
920 FilterFile
|| (bIndex
&& indexfile
);
921 bCompare
= Vec2File
|| Eig2File
;
922 bPDB3D
= fn2ftp(ThreeDPlotFile
)==efPDB
;
924 read_eigenvectors(VecFile
,&natoms
,&bFit1
,
925 &xref1
,&bDMR1
,&xav1
,&bDMA1
,
926 &nvec1
,&eignr1
,&eigvec1
,&eigval1
);
929 /* Overwrite eigenvalues from separate files if the user provides them */
930 if (EigFile
!= NULL
) {
931 int neig_tmp
= read_xvg(EigFile
,&xvgdata
,&i
);
932 if (neig_tmp
!= neig1
)
933 fprintf(stderr
,"Warning: number of eigenvalues in xvg file (%d) does not mtch trr file (%d)\n",neig1
,natoms
);
935 srenew(eigval1
,neig1
);
936 for(j
=0;j
<neig1
;j
++) {
937 real tmp
= eigval1
[j
];
938 eigval1
[j
]=xvgdata
[1][j
];
939 if (debug
&& (eigval1
[j
] != tmp
))
940 fprintf(debug
,"Replacing eigenvalue %d. From trr: %10g, from xvg: %10g\n",
946 fprintf(stderr
,"Read %d eigenvalues from %s\n",neig1
,EigFile
);
950 calc_entropy_qh(stdout
,neig1
,eigval1
,temp
,nskip
);
951 calc_entropy_schlitter(stdout
,neig1
,nskip
,eigval1
,temp
);
956 gmx_fatal(FARGS
,"Need a second eigenvector file to do this analysis.");
957 read_eigenvectors(Vec2File
,&neig2
,&bFit2
,
958 &xref2
,&bDMR2
,&xav2
,&bDMA2
,&nvec2
,&eignr2
,&eigvec2
,&eigval2
);
962 gmx_fatal(FARGS
,"Dimensions in the eigenvector files don't match");
965 if(Eig2File
!= NULL
) {
966 neig2
= read_xvg(Eig2File
,&xvgdata
,&i
);
967 srenew(eigval2
,neig2
);
969 eigval2
[j
]=xvgdata
[1][j
];
973 fprintf(stderr
,"Read %d eigenvalues from %s\n",neig2
,Eig2File
);
977 if ((!bFit1
|| xref1
) && !bDMR1
&& !bDMA1
)
979 if ((xref1
==NULL
) && (bM
|| bTraj
))
989 bTop
=read_tps_conf(ftp2fn(efTPS
,NFILE
,fnm
),
990 title
,&top
,&ePBC
,&xtop
,NULL
,topbox
,bM
);
992 rm_pbc(&(top
.idef
),ePBC
,atoms
->nr
,topbox
,xtop
,xtop
);
993 /* Fitting is only needed when we need to read a trajectory */
995 if ((xref1
==NULL
) || (bM
&& bDMR1
)) {
997 printf("\nNote: the structure in %s should be the same\n"
998 " as the one used for the fit in g_covar\n",topfile
);
999 printf("\nSelect the index group that was used for the least squares fit in g_covar\n");
1000 get_index(atoms
,indexfile
,1,&nfit
,&ifit
,&grpname
);
1001 snew(w_rls
,atoms
->nr
);
1002 for(i
=0; (i
<nfit
); i
++) {
1004 w_rls
[ifit
[i
]]=atoms
->atom
[ifit
[i
]].m
;
1010 /* make the fit index in xref instead of xtop */
1014 for(i
=0; (i
<nfit
); i
++) {
1016 w_rls
[i
]=atoms
->atom
[ifit
[i
]].m
;
1021 /* make the fit non mass weighted on xref */
1025 for(i
=0; i
<nfit
; i
++) {
1034 printf("\nSelect an index group of %d elements that corresponds to the eigenvectors\n",natoms
);
1035 get_index(atoms
,indexfile
,1,&i
,&index
,&grpname
);
1037 gmx_fatal(FARGS
,"you selected a group with %d elements instead of %d",i
,natoms
);
1043 proj_unit
="u\\S1/2\\Nnm";
1044 for(i
=0; (i
<natoms
); i
++)
1045 sqrtm
[i
]=sqrt(atoms
->atom
[index
[i
]].m
);
1049 for(i
=0; (i
<natoms
); i
++)
1056 for(i
=0; (i
<natoms
); i
++)
1057 for(d
=0;(d
<DIM
);d
++) {
1058 t
+=sqr((xav1
[i
][d
]-xav2
[i
][d
])*sqrtm
[i
]);
1059 totmass
+=sqr(sqrtm
[i
]);
1061 fprintf(stdout
,"RMSD (without fit) between the two average structures:"
1062 " %.3f (nm)\n\n",sqrt(t
/totmass
));
1069 /* make an index from first to last */
1072 for(i
=0; i
<nout
; i
++)
1075 else if (ThreeDPlotFile
) {
1076 /* make an index of first+(0,1,2) and last */
1077 nout
= bPDB3D
? 4 : 3;
1078 nout
= min(last
-first
+1, nout
);
1084 iout
[nout
-1]=last
-1;
1087 /* make an index of first and last */
1095 printf("Select eigenvectors for output, end your selection with 0\n");
1101 srenew(iout
,nout
+1);
1102 if(1 != scanf("%d",&iout
[nout
]))
1104 gmx_fatal(FARGS
,"Error reading user input");
1108 while (iout
[nout
]>=0);
1112 /* make an index of the eigenvectors which are present */
1115 for(i
=0; i
<nout
; i
++)
1118 while ((j
<nvec1
) && (eignr1
[j
]!=iout
[i
]))
1120 if ((j
<nvec1
) && (eignr1
[j
]==iout
[i
]))
1126 fprintf(stderr
,"%d eigenvectors selected for output",noutvec
);
1129 fprintf(stderr
,":");
1130 for(j
=0; j
<noutvec
; j
++)
1131 fprintf(stderr
," %d",eignr1
[outvec
[j
]]+1);
1133 fprintf(stderr
,"\n");
1136 components(CompFile
,natoms
,eignr1
,eigvec1
,noutvec
,outvec
,oenv
);
1139 rmsf(RmsfFile
,natoms
,sqrtm
,eignr1
,eigvec1
,noutvec
,outvec
,eigval1
,
1143 project(bTraj
? opt2fn("-f",NFILE
,fnm
) : NULL
,
1144 bTop
? &top
: NULL
,ePBC
,topbox
,xtop
,
1145 ProjOnVecFile
,TwoDPlotFile
,ThreeDPlotFile
,FilterFile
,skip
,
1146 ExtremeFile
,bFirstLastSet
,max
,nextr
,atoms
,natoms
,index
,
1147 bFit1
,xref1
,nfit
,ifit
,w_rls
,
1148 sqrtm
,xav1
,eignr1
,eigvec1
,noutvec
,outvec
,bSplit
,
1152 overlap(OverlapFile
,natoms
,
1153 eigvec1
,nvec2
,eignr2
,eigvec2
,noutvec
,outvec
,oenv
);
1156 inprod_matrix(InpMatFile
,natoms
,
1157 nvec1
,eignr1
,eigvec1
,nvec2
,eignr2
,eigvec2
,
1158 bFirstLastSet
,noutvec
,outvec
);
1161 compare(natoms
,nvec1
,eigvec1
,nvec2
,eigvec2
,eigval1
,neig1
,eigval2
,neig2
);
1164 if (!CompFile
&& !bProj
&& !OverlapFile
&& !InpMatFile
&&
1165 !bCompare
&& !bEntropy
)
1167 fprintf(stderr
,"\nIf you want some output,"
1168 " set one (or two or ...) of the output file options\n");
1172 view_all(oenv
,NFILE
, fnm
);