2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2012,2013,2014,2015,2017,2018, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
37 #include "gromacs/commandline/filenm.h"
38 #include "gromacs/commandline/pargs.h"
39 #include "gromacs/fileio/trxio.h"
40 #include "gromacs/fileio/xvgr.h"
41 #include "gromacs/gmxana/gmx_ana.h"
42 #include "gromacs/math/vec.h"
43 #include "gromacs/pbcutil/pbc.h"
44 #include "gromacs/topology/index.h"
45 #include "gromacs/trajectory/trajectoryframe.h"
46 #include "gromacs/utility/arraysize.h"
47 #include "gromacs/utility/fatalerror.h"
48 #include "gromacs/utility/futil.h"
49 #include "gromacs/utility/pleasecite.h"
50 #include "gromacs/utility/smalloc.h"
52 int gmx_dyecoupl(int argc
, char *argv
[])
56 "[THISMODULE] extracts dye dynamics from trajectory files.",
57 "Currently, R and kappa^2 between dyes is extracted for (F)RET",
58 "simulations with assumed dipolar coupling as in the Foerster equation.",
59 "It further allows the calculation of R(t) and kappa^2(t), R and",
60 "kappa^2 histograms and averages, as well as the instantaneous FRET",
61 "efficiency E(t) for a specified Foerster radius R_0 (switch [TT]-R0[tt]).",
62 "The input dyes have to be whole (see res and mol pbc options",
63 "in [TT]trjconv[tt]).",
64 "The dye transition dipole moment has to be defined by at least",
65 "a single atom pair, however multiple atom pairs can be provided ",
66 "in the index file. The distance R is calculated on the basis of",
67 "the COMs of the given atom pairs.",
68 "The [TT]-pbcdist[tt] option calculates distances to the nearest periodic",
69 "image instead to the distance in the box. This works however only,",
70 "for periodic boundaries in all 3 dimensions.",
71 "The [TT]-norm[tt] option (area-) normalizes the histograms."
74 static gmx_bool bPBCdist
= FALSE
, bNormHist
= FALSE
;
76 gmx_output_env_t
*oenv
;
81 { "-pbcdist", FALSE
, etBOOL
, { &bPBCdist
}, "Distance R based on PBC" },
82 { "-norm", FALSE
, etBOOL
, { &bNormHist
}, "Normalize histograms" },
83 { "-bins", FALSE
, etINT
, {&histbins
}, "# of histogram bins" },
84 { "-R0", FALSE
, etREAL
, {&R0
}, "Foerster radius including kappa^2=2/3 in nm" }
90 { efTRX
, "-f", nullptr, ffREAD
},
91 { efNDX
, nullptr, nullptr, ffREAD
},
92 { efXVG
, "-ot", "rkappa", ffOPTWR
},
93 { efXVG
, "-oe", "insteff", ffOPTWR
},
94 { efDAT
, "-o", "rkappa", ffOPTWR
},
95 { efXVG
, "-rhist", "rhist", ffOPTWR
},
96 { efXVG
, "-khist", "khist", ffOPTWR
}
98 #define NFILE asize(fnm)
101 const char *in_trajfile
, *out_xvgrkfile
= nullptr, *out_xvginstefffile
= nullptr, *out_xvgrhistfile
= nullptr, *out_xvgkhistfile
= nullptr, *out_datfile
= nullptr;
102 gmx_bool bHaveFirstFrame
, bHaveNextFrame
, indexOK
= TRUE
;
104 int *donindex
, *accindex
;
110 int allocblock
= 1000;
111 real histexpand
= 1e-6;
112 rvec donvec
, accvec
, donpos
, accpos
, dist
, distnorm
;
115 /*we rely on PBC autodetection (...currently)*/
118 real
*rvalues
= nullptr, *kappa2values
= nullptr, *rhist
= nullptr, *khist
= nullptr;
119 t_pbc
*pbc
= nullptr;
121 FILE *rkfp
= nullptr, *rhfp
= nullptr, *khfp
= nullptr, *datfp
= nullptr, *iefp
= nullptr;
122 gmx_bool bRKout
, bRhistout
, bKhistout
, bDatout
, bInstEffout
, grident
;
124 const char *rkleg
[2] = { "R", "\\f{Symbol}k\\f{}\\S2\\N" };
125 const char *rhleg
[1] = { "p(R)" };
126 const char *khleg
[1] = { "p(\\f{Symbol}k\\f{}\\S2\\N)" };
127 const char *ieleg
[1] = { "E\\sRET\\N(t)" };
129 real R
, kappa2
, insteff
, Rs
= 0., kappa2s
= 0., insteffs
= 0., rmax
, rmin
, kmin
= 0., kmax
= 4.,
130 rrange
, krange
, rincr
, kincr
, Rfrac
;
131 int rkcount
= 0, rblocksallocated
= 0, kblocksallocated
= 0;
133 if (!parse_common_args(&argc
, argv
, PCA_CAN_BEGIN
| PCA_CAN_END
| PCA_CAN_VIEW
| PCA_TIME_UNIT
,
134 NFILE
, fnm
, NPA
, pa
, asize(desc
), desc
, 0, nullptr, &oenv
))
140 /* Check command line options for filenames and set bool flags when switch used*/
141 in_trajfile
= opt2fn("-f", NFILE
, fnm
);
142 out_xvgrkfile
= opt2fn("-ot", NFILE
, fnm
);
143 out_xvgrhistfile
= opt2fn("-rhist", NFILE
, fnm
);
144 out_xvgkhistfile
= opt2fn("-khist", NFILE
, fnm
);
145 out_xvginstefffile
= opt2fn("-oe", NFILE
, fnm
);
146 out_datfile
= opt2fn("-o", NFILE
, fnm
);
148 bRKout
= opt2bSet("-ot", NFILE
, fnm
);
149 bRhistout
= opt2bSet("-rhist", NFILE
, fnm
);
150 bKhistout
= opt2bSet("-khist", NFILE
, fnm
);
151 bDatout
= opt2bSet("-o", NFILE
, fnm
);
152 bInstEffout
= opt2bSet("-oe", NFILE
, fnm
);
158 printf("Calculating distances to periodic image.\n");
159 printf("Be careful! This produces only valid results for PBC in all three dimensions\n");
163 if (bInstEffout
&& R0
<= 0.)
165 gmx_fatal(FARGS
, "You have to specify R0 and R0 has to be larger than 0 nm.\n\n");
168 printf("Select group with donor atom pairs defining the transition moment\n");
169 get_index(nullptr, ftp2fn_null(efNDX
, NFILE
, fnm
), 1, &ndon
, &donindex
, &grpnm
);
171 printf("Select group with acceptor atom pairs defining the transition moment\n");
172 get_index(nullptr, ftp2fn_null(efNDX
, NFILE
, fnm
), 1, &nacc
, &accindex
, &grpnm
);
174 /*check if groups are identical*/
179 for (i
= 0; i
< nacc
; i
++)
181 if (accindex
[i
] != donindex
[i
])
191 gmx_fatal(FARGS
, "Donor and acceptor group are identical. This makes no sense.");
194 printf("Reading first frame\n");
195 /* open trx file for reading */
197 flags
= flags
| TRX_READ_X
;
198 bHaveFirstFrame
= read_first_frame(oenv
, &status
, in_trajfile
, &fr
, flags
);
202 printf("First frame is OK\n");
204 if ((ndon
% 2 != 0) || (nacc
% 2 != 0))
210 for (i
= 0; i
< ndon
; i
++)
212 if (donindex
[i
] >= natoms
)
217 for (i
= 0; i
< nacc
; i
++)
219 if (accindex
[i
] >= natoms
)
231 datfp
= gmx_ffopen(out_datfile
, "w");
236 rkfp
= xvgropen(out_xvgrkfile
,
237 "Distance and \\f{Symbol}k\\f{}\\S2\\N trajectory",
238 "Time (ps)", "Distance (nm) / \\f{Symbol}k\\f{}\\S2\\N",
240 xvgr_legend(rkfp
, 2, rkleg
, oenv
);
245 iefp
= xvgropen(out_xvginstefffile
,
246 "Instantaneous RET Efficiency",
247 "Time (ps)", "RET Efficiency",
249 xvgr_legend(iefp
, 1, ieleg
, oenv
);
255 snew(rvalues
, allocblock
);
256 rblocksallocated
+= 1;
257 snew(rhist
, histbins
);
262 snew(kappa2values
, allocblock
);
263 kblocksallocated
+= 1;
264 snew(khist
, histbins
);
273 for (i
= 0; i
< ndon
/ 2; i
++)
275 rvec_sub(donvec
, fr
.x
[donindex
[2 * i
]], donvec
);
276 rvec_add(donvec
, fr
.x
[donindex
[2 * i
+ 1]], donvec
);
277 rvec_add(donpos
, fr
.x
[donindex
[2 * i
]], donpos
);
278 rvec_add(donpos
, fr
.x
[donindex
[2 * i
+ 1]], donpos
);
281 for (i
= 0; i
< nacc
/ 2; i
++)
283 rvec_sub(accvec
, fr
.x
[accindex
[2 * i
]], accvec
);
284 rvec_add(accvec
, fr
.x
[accindex
[2 * i
+ 1]], accvec
);
285 rvec_add(accpos
, fr
.x
[accindex
[2 * i
]], accpos
);
286 rvec_add(accpos
, fr
.x
[accindex
[2 * i
+ 1]], accpos
);
289 unitv(donvec
, donvec
);
290 unitv(accvec
, accvec
);
292 svmul(1.0 / ndon
, donpos
, donpos
);
293 svmul(1.0 / nacc
, accpos
, accpos
);
297 set_pbc(pbc
, ePBC
, fr
.box
);
298 pbc_dx(pbc
, donpos
, accpos
, dist
);
302 rvec_sub(donpos
, accpos
, dist
);
305 unitv(dist
, distnorm
);
307 kappa2
= iprod(donvec
, accvec
)- 3.* (iprod(donvec
, distnorm
) * iprod(distnorm
, accvec
));
312 insteff
= 1/(1+(Rfrac
*Rfrac
*Rfrac
*Rfrac
*Rfrac
*Rfrac
)*2/3/kappa2
);
317 fprintf(iefp
, "%12.7f %12.7f\n", fr
.time
, insteff
);
328 fprintf(rkfp
, "%12.7f %12.7f %12.7f\n", fr
.time
, R
, kappa2
);
333 fprintf(datfp
, "%12.7f %12.7f %12.7f\n", fr
.time
, R
, kappa2
);
338 rvalues
[rkcount
-1] = R
;
339 if (rkcount
% allocblock
== 0)
341 srenew(rvalues
, allocblock
*(rblocksallocated
+1));
342 rblocksallocated
+= 1;
348 kappa2values
[rkcount
-1] = kappa2
;
349 if (rkcount
% allocblock
== 0)
351 srenew(kappa2values
, allocblock
*(kblocksallocated
+1));
352 kblocksallocated
+= 1;
356 bHaveNextFrame
= read_next_frame(oenv
, status
, &fr
);
358 while (bHaveNextFrame
);
378 printf("Writing R-Histogram\n");
381 for (i
= 1; i
< rkcount
; i
++)
383 if (rvalues
[i
] < rmin
)
387 else if (rvalues
[i
] > rmax
)
395 rrange
= rmax
- rmin
;
396 rincr
= rrange
/ histbins
;
398 for (i
= 1; i
< rkcount
; i
++)
400 bin
= static_cast<int>((rvalues
[i
] - rmin
) / rincr
);
405 for (i
= 0; i
< histbins
; i
++)
407 rhist
[i
] /= rkcount
* rrange
/histbins
;
409 rhfp
= xvgropen(out_xvgrhistfile
, "Distance Distribution",
410 "R (nm)", "Normalized Probability", oenv
);
414 rhfp
= xvgropen(out_xvgrhistfile
, "Distance Distribution",
415 "R (nm)", "Probability", oenv
);
417 xvgr_legend(rhfp
, 1, rhleg
, oenv
);
418 for (i
= 0; i
< histbins
; i
++)
420 fprintf(rhfp
, "%12.7f %12.7f\n", (i
+ 0.5) * rincr
+ rmin
,
428 printf("Writing kappa^2-Histogram\n");
429 krange
= kmax
- kmin
;
430 kincr
= krange
/ histbins
;
432 for (i
= 1; i
< rkcount
; i
++)
434 bin
= static_cast<int>((kappa2values
[i
] - kmin
) / kincr
);
439 for (i
= 0; i
< histbins
; i
++)
441 khist
[i
] /= rkcount
* krange
/histbins
;
443 khfp
= xvgropen(out_xvgkhistfile
,
444 "\\f{Symbol}k\\f{}\\S2\\N Distribution",
445 "\\f{Symbol}k\\f{}\\S2\\N",
446 "Normalized Probability", oenv
);
450 khfp
= xvgropen(out_xvgkhistfile
,
451 "\\f{Symbol}k\\f{}\\S2\\N Distribution",
452 "\\f{Symbol}k\\f{}\\S2\\N", "Probability", oenv
);
454 xvgr_legend(khfp
, 1, khleg
, oenv
);
455 for (i
= 0; i
< histbins
; i
++)
457 fprintf(khfp
, "%12.7f %12.7f\n", (i
+ 0.5) * kincr
+ kmin
,
463 printf("\nAverages:\n");
464 printf("R_avg = %8.4f nm\nKappa^2 = %8.4f\n", Rs
/ rkcount
,
468 printf("E_RETavg = %8.4f\n", insteffs
/ rkcount
);
470 please_cite(stdout
, "Hoefling2011");
474 gmx_fatal(FARGS
, "Index file invalid, check your index file for correct pairs.\n");
479 gmx_fatal(FARGS
, "Could not read first frame of the trajectory.\n");