3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
9 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11 * Copyright (c) 2001-2009, The GROMACS development team,
12 * check out http://www.gromacs.org for more information.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * If you want to redistribute modifications, please consider that
20 * scientific software is very special. Version control is crucial -
21 * bugs must be traceable. We will be happy to consider code for
22 * inclusion in the official distribution, but derived work must not
23 * be called official GROMACS. Details are found in the README & COPYING
24 * files - if they are missing, get the official version at www.gromacs.org.
26 * To help us fund GROMACS development, we humbly ask that you cite
27 * the papers on the package - you can find them in the top README file.
29 * For more info, check our website at http://www.gromacs.org
32 #include "gromacs/fileio/filenm.h"
39 #include "gromacs/fileio/trxio.h"
42 int gmx_dyecoupl(int argc, char *argv[])
46 "[THISMODULE] extracts dye dynamics from trajectory files.",
47 "Currently, R and kappa^2 between dyes is extracted for (F)RET",
48 "simulations with assumed dipolar coupling as in the Foerster equation.",
49 "It further allows the calculation of R(t) and kappa^2(t), R and",
50 "kappa^2 histograms and averages, as well as the instantaneous FRET",
51 "efficiency E(t) for a specified Foerster radius R_0 (switch [TT]-R0[tt]).",
52 "The input dyes have to be whole (see res and mol pbc options",
53 "in [TT]trjconv[tt]).",
54 "The dye transition dipole moment has to be defined by at least",
55 "a single atom pair, however multiple atom pairs can be provided ",
56 "in the index file. The distance R is calculated on the basis of",
57 "the COMs of the given atom pairs.",
58 "The [TT]-pbcdist[tt] option calculates distances to the nearest periodic",
59 "image instead to the distance in the box. This works however only,"
60 "for periodic boundaries in all 3 dimensions.",
61 "The [TT]-norm[tt] option (area-) normalizes the histograms."
64 static gmx_bool bPBCdist = FALSE, bNormHist = FALSE;
71 { "-pbcdist", FALSE, etBOOL, { &bPBCdist }, "Distance R based on PBC" },
72 { "-norm", FALSE, etBOOL, { &bNormHist }, "Normalize histograms" },
73 { "-bins", FALSE, etINT, {&histbins}, "# of histogram bins" },
74 { "-R0", FALSE, etREAL, {&R0}, "Foerster radius including kappa^2=2/3 in nm" }
80 { efTRX, "-f", NULL, ffREAD },
81 { efNDX, NULL, NULL, ffREAD },
82 { efXVG, "-ot", "rkappa", ffOPTWR },
83 { efXVG, "-oe", "insteff", ffOPTWR },
84 { efDAT, "-o", "rkappa", ffOPTWR },
85 { efXVG, "-rhist", "rhist", ffOPTWR },
86 { efXVG, "-khist", "khist", ffOPTWR }
88 #define NFILE asize(fnm)
91 const char *in_trajfile, *in_ndxfile, *out_xvgrkfile = NULL, *out_xvginstefffile = NULL, *out_xvgrhistfile = NULL, *out_xvgkhistfile = NULL, *out_datfile = NULL;
92 gmx_bool bHaveFirstFrame, bHaveNextFrame, indexOK = TRUE;
94 atom_id *donindex, *accindex;
96 t_atoms *atoms = NULL;
101 int allocblock = 1000;
102 real histexpand = 1e-6;
103 rvec donvec, accvec, donpos, accpos, dist, distnorm;
106 /*we rely on PBC autodetection (...currently)*/
109 real *rvalues = NULL, *kappa2values = NULL, *rhist = NULL, *khist = NULL;
112 FILE *rkfp = NULL, *rhfp = NULL, *khfp = NULL, *datfp = NULL, *iefp = NULL;
113 gmx_bool bRKout, bRhistout, bKhistout, bDatout, bInstEffout, grident;
115 const char *rkleg[2] = { "R", "\\f{Symbol}k\\f{}\\S2\\N" };
116 const char *rhleg[1] = { "p(R)" };
117 const char *khleg[1] = { "p(\\f{Symbol}k\\f{}\\S2\\N)" };
118 const char *ieleg[1] = { "E\\sRET\\N(t)" };
120 real R, kappa2, insteff, Rs = 0., kappa2s = 0., insteffs = 0., rmax, rmin, kmin = 0., kmax = 4.,
121 rrange, krange, rincr, kincr, Rfrac;
122 int rkcount = 0, rblocksallocated = 0, kblocksallocated = 0;
124 if (!parse_common_args(&argc, argv, PCA_CAN_BEGIN | PCA_CAN_END | PCA_CAN_VIEW | PCA_TIME_UNIT | PCA_BE_NICE, NFILE, fnm, NPA, pa, asize(desc), desc, 0, NULL, &oenv))
130 /* Check command line options for filenames and set bool flags when switch used*/
131 in_trajfile = opt2fn("-f", NFILE, fnm);
132 in_ndxfile = opt2fn("-n", NFILE, fnm);
133 out_xvgrkfile = opt2fn("-ot", NFILE, fnm);
134 out_xvgrhistfile = opt2fn("-rhist", NFILE, fnm);
135 out_xvgkhistfile = opt2fn("-khist", NFILE, fnm);
136 out_xvginstefffile = opt2fn("-oe", NFILE, fnm);
137 out_datfile = opt2fn("-o", NFILE, fnm);
139 bRKout = opt2bSet("-ot", NFILE, fnm);
140 bRhistout = opt2bSet("-rhist", NFILE, fnm);
141 bKhistout = opt2bSet("-khist", NFILE, fnm);
142 bDatout = opt2bSet("-o", NFILE, fnm);
143 bInstEffout = opt2bSet("-oe", NFILE, fnm);
149 printf("Calculating distances to periodic image.\n");
150 printf("Be careful! This produces only valid results for PBC in all three dimensions\n");
154 if (bInstEffout && R0 <= 0.)
156 gmx_fatal(FARGS, "You have to specify R0 and R0 has to be larger than 0 nm.\n\n");
159 printf("Select group with donor atom pairs defining the transition moment\n");
160 get_index(atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &ndon, &donindex, &grpnm);
162 printf("Select group with acceptor atom pairs defining the transition moment\n");
163 get_index(atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &nacc, &accindex, &grpnm);
165 /*check if groups are identical*/
170 for (i = 0; i < nacc; i++)
172 if (accindex[i] != donindex[i])
182 gmx_fatal(FARGS, "Donor and acceptor group are identical. This makes no sense.");
185 printf("Reading first frame\n");
186 /* open trx file for reading */
188 flags = flags | TRX_READ_X;
189 bHaveFirstFrame = read_first_frame(oenv, &status, in_trajfile, &fr, flags);
193 printf("First frame is OK\n");
195 if ((ndon % 2 != 0) || (nacc % 2 != 0))
201 for (i = 0; i < ndon; i++)
203 if (donindex[i] >= natoms)
208 for (i = 0; i < nacc; i++)
210 if (accindex[i] >= natoms)
222 datfp = fopen(out_datfile, "w");
227 rkfp = xvgropen(out_xvgrkfile,
228 "Distance and \\f{Symbol}k\\f{}\\S2\\N trajectory",
229 "Time (ps)", "Distance (nm) / \\f{Symbol}k\\f{}\\S2\\N",
231 xvgr_legend(rkfp, 2, rkleg, oenv);
236 iefp = xvgropen(out_xvginstefffile,
237 "Instantaneous RET Efficiency",
238 "Time (ps)", "RET Efficiency",
240 xvgr_legend(iefp, 1, ieleg, oenv);
246 snew(rvalues, allocblock);
247 rblocksallocated += 1;
248 snew(rhist, histbins);
253 snew(kappa2values, allocblock);
254 kblocksallocated += 1;
255 snew(khist, histbins);
264 for (i = 0; i < ndon / 2; i++)
266 rvec_sub(donvec, fr.x[donindex[2 * i]], donvec);
267 rvec_add(donvec, fr.x[donindex[2 * i + 1]], donvec);
268 rvec_add(donpos, fr.x[donindex[2 * i]], donpos);
269 rvec_add(donpos, fr.x[donindex[2 * i + 1]], donpos);
272 for (i = 0; i < nacc / 2; i++)
274 rvec_sub(accvec, fr.x[accindex[2 * i]], accvec);
275 rvec_add(accvec, fr.x[accindex[2 * i + 1]], accvec);
276 rvec_add(accpos, fr.x[accindex[2 * i]], accpos);
277 rvec_add(accpos, fr.x[accindex[2 * i + 1]], accpos);
280 unitv(donvec, donvec);
281 unitv(accvec, accvec);
283 svmul((real) 1. / ndon, donpos, donpos);
284 svmul((real) 1. / nacc, accpos, accpos);
288 set_pbc(pbc, ePBC, fr.box);
289 pbc_dx(pbc, donpos, accpos, dist);
293 rvec_sub(donpos, accpos, dist);
296 unitv(dist, distnorm);
298 kappa2 = iprod(donvec, accvec)- 3.* (iprod(donvec, distnorm) * iprod(distnorm, accvec));
303 insteff = 1/(1+(Rfrac*Rfrac*Rfrac*Rfrac*Rfrac*Rfrac)*2/3/kappa2);
308 fprintf(iefp, "%12.7f %12.7f\n", fr.time, insteff);
319 fprintf(rkfp, "%12.7f %12.7f %12.7f\n", fr.time, R, kappa2);
324 fprintf(datfp, "%12.7f %12.7f %12.7f\n", fr.time, R, kappa2);
329 rvalues[rkcount-1] = R;
330 if (rkcount % allocblock == 0)
332 srenew(rvalues, allocblock*(rblocksallocated+1));
333 rblocksallocated += 1;
339 kappa2values[rkcount-1] = kappa2;
340 if (rkcount % allocblock == 0)
342 srenew(kappa2values, allocblock*(kblocksallocated+1));
343 kblocksallocated += 1;
347 bHaveNextFrame = read_next_frame(oenv, status, &fr);
349 while (bHaveNextFrame);
369 printf("Writing R-Histogram\n");
372 for (i = 1; i < rkcount; i++)
374 if (rvalues[i] < rmin)
378 else if (rvalues[i] > rmax)
386 rrange = rmax - rmin;
387 rincr = rrange / histbins;
389 for (i = 1; i < rkcount; i++)
391 bin = (int) ((rvalues[i] - rmin) / rincr);
396 for (i = 0; i < histbins; i++)
398 rhist[i] /= rkcount * rrange/histbins;
400 rhfp = xvgropen(out_xvgrhistfile, "Distance Distribution",
401 "R (nm)", "Normalized Probability", oenv);
405 rhfp = xvgropen(out_xvgrhistfile, "Distance Distribution",
406 "R (nm)", "Probability", oenv);
408 xvgr_legend(rhfp, 1, rhleg, oenv);
409 for (i = 0; i < histbins; i++)
411 fprintf(rhfp, "%12.7f %12.7f\n", (i + 0.5) * rincr + rmin,
419 printf("Writing kappa^2-Histogram\n");
420 krange = kmax - kmin;
421 kincr = krange / histbins;
423 for (i = 1; i < rkcount; i++)
425 bin = (int) ((kappa2values[i] - kmin) / kincr);
430 for (i = 0; i < histbins; i++)
432 khist[i] /= rkcount * krange/histbins;
434 khfp = xvgropen(out_xvgkhistfile,
435 "\\f{Symbol}k\\f{}\\S2\\N Distribution",
436 "\\f{Symbol}k\\f{}\\S2\\N",
437 "Normalized Probability", oenv);
441 khfp = xvgropen(out_xvgkhistfile,
442 "\\f{Symbol}k\\f{}\\S2\\N Distribution",
443 "\\f{Symbol}k\\f{}\\S2\\N", "Probability", oenv);
445 xvgr_legend(khfp, 1, khleg, oenv);
446 for (i = 0; i < histbins; i++)
448 fprintf(khfp, "%12.7f %12.7f\n", (i + 0.5) * kincr + kmin,
454 printf("\nAverages:\n");
455 printf("R_avg = %8.4f nm\nKappa^2 = %8.4f\n", Rs / rkcount,
459 printf("E_RETavg = %8.4f\n", insteffs / rkcount);
461 please_cite(stdout, "Hoefling2011");
465 gmx_fatal(FARGS, "Index file invalid, check your index file for correct pairs.\n");
470 gmx_fatal(FARGS, "Could not read first frame of the trajectory.\n");