layout: post title: GROMACS计算距离的方法及注意点 categories:
低版本的GROMACS中(具体哪个版本就没有考古了, 猜想是3.x吧), g_distance
计算距离时需要选择两个组, 然后程序会自动计算这两个组的原子两两配对之间的距离, 也可以计算这两个组的质心之间的距离. 可能是从4.x版本起吧, gmx distance
使用的索引组的方法有了变化, 可以提供多个索引组, 每个组是独立的, 在其中列出要计算的原子对. 因此要计算距离的组中总原子个数必须是偶数, 否则会给出原子数目非偶数的错误. 例如, 我们要计算体系中3
号原子和5
, 9
, 13
, 19
之间的距离, 那么可以在索引文件中定义如下组
编号对也可以放于多行中, 每行一个原子对编号. 但值得注意的是, 至少在我测试的 2016.4版本中, 在处理这些编号对时, GROMACS存在错误, 对1 2 2 3
这样的编号对, 会先将中间重复的编号合并为一个, 变成1 2 3
, 从而导致无法计算. 解决办法也很简单, 就是更换顺序, 保证相邻编号之间不存在重复. 如上面的例子改成1 2 3 2
就可以正常计算了.
采用这种模式, 需要我们自己提供要计算的原子对. 当原子数较少时并无困难, 但原子数一多起来, 组合就多了, 手写不太现实, 所以我就写了一段代码来处理这个问题.
<table class="highlighttable"><th colspan="2" style="text-align:left">gmx_ndx.bsh</th><tr><td><div class="linenodiv" style="background-color: #f0f0f0; padding-right: 10px"><pre style="line-height: 125%"> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34</pre></div></td><td class="code"><div class="highlight"><pre style="line-height:125%"><span></span><span style="color: #B8860B">usage</span><span style="color: #666666">=</span><span style="color: #BB4444">"\</span> <span style="color: #BB4444">>>>>>>>>>>>>>>>> gmx_ndx <<<<<<<<<<<<<<<<</span> <span style="color: #BB4444">>>>>>>>>>>>>>>>> Jicun LI <<<<<<<<<<<<<<<<</span> <span style="color: #BB4444">>>>>>>>>>> 2016-09-15 09:49:36 <<<<<<<<<</span> <span style="color: #BB4444">>> Usage: gmx_ndx <File.ndx> [Group 1] [Group 2]</span> <span style="color: #BB4444">>> Default: gmx_ndx N/A Other SOL"</span> <span style="color: #666666">[[</span> <span style="color: #B8860B">$#</span> -lt <span style="color: #666666">1</span> <span style="color: #666666">]]</span> <span style="color: #666666">&&</span> <span style="color: #666666">{</span> <span style="color: #AA22FF">echo</span> <span style="color: #BB4444">"</span><span style="color: #B8860B">$usage</span><span style="color: #BB4444">"</span>; exit; <span style="color: #666666">}</span> <span style="color: #B8860B">File</span><span style="color: #666666">=</span>index; <span style="color: #666666">[[</span> <span style="color: #B8860B">$#</span> -ge <span style="color: #666666">1</span> <span style="color: #666666">]]</span> <span style="color: #666666">&&</span> <span style="color: #666666">{</span> <span style="color: #B8860B">File</span><span style="color: #666666">=</span><span style="color: #BB6688; font-weight: bold">${</span><span style="color: #B8860B">1</span>%.ndx<span style="color: #BB6688; font-weight: bold">}</span>; <span style="color: #666666">}</span> <span style="color: #B8860B">Grp1</span><span style="color: #666666">=</span>Other; <span style="color: #666666">[[</span> <span style="color: #B8860B">$#</span> -ge <span style="color: #666666">2</span> <span style="color: #666666">]]</span> <span style="color: #666666">&&</span> <span style="color: #666666">{</span> <span style="color: #B8860B">Grp1</span><span style="color: #666666">=</span><span style="color: #B8860B">$2</span>; <span style="color: #666666">}</span> <span style="color: #B8860B">Grp2</span><span style="color: #666666">=</span>SOL; <span style="color: #666666">[[</span> <span style="color: #B8860B">$#</span> -ge <span style="color: #666666">3</span> <span style="color: #666666">]]</span> <span style="color: #666666">&&</span> <span style="color: #666666">{</span> <span style="color: #B8860B">Grp2</span><span style="color: #666666">=</span><span style="color: #B8860B">$3</span>; <span style="color: #666666">}</span> <span style="color: #AA22FF">echo</span> -e <span style="color: #BB4444">"\n生成 </span><span style="color: #B8860B">$Grp1</span><span style="color: #BB4444"> 与 </span><span style="color: #B8860B">$Grp2</span><span style="color: #BB4444"> 的组合新组 [ </span><span style="color: #BB6688; font-weight: bold">${</span><span style="color: #B8860B">Grp1</span><span style="color: #BB6688; font-weight: bold">}</span><span style="color: #BB4444">_</span><span style="color: #B8860B">$Grp2</span><span style="color: #BB4444"> ] 并追加到 </span><span style="color: #B8860B">$File</span><span style="color: #BB4444">.ndx 文件"</span> awk -v <span style="color: #B8860B">Grp1</span><span style="color: #666666">=</span><span style="color: #B8860B">$Grp1</span> -v <span style="color: #B8860B">Grp2</span><span style="color: #666666">=</span><span style="color: #B8860B">$Grp2</span> <span style="color: #BB4444">'</span> BEGIN<span style="color: #666666">{</span> <span style="color: #B8860B">RS</span><span style="color: #666666">=</span><span style="color: #BB4444">"["</span> <span style="color: #666666">}</span> <span style="color: #B8860B">$1</span><span style="color: #666666">==</span>Grp1 <span style="color: #666666">{</span> <span style="color: #B8860B">N1</span><span style="color: #666666">=</span>NF-2 <span style="color: #AA22FF; font-weight: bold">for</span><span style="color: #666666">(</span><span style="color: #B8860B">i</span><span style="color: #666666">=</span>1; i<<span style="color: #666666">=</span>N1; i++<span style="color: #666666">)</span> G1<span style="color: #666666">[</span>i<span style="color: #666666">]=</span><span style="color: #AA22FF; font-weight: bold">$(</span>i+2<span style="color: #AA22FF; font-weight: bold">)</span> <span style="color: #666666">}</span> <span style="color: #B8860B">$1</span><span style="color: #666666">==</span>Grp2 <span style="color: #666666">{</span> <span style="color: #B8860B">N2</span><span style="color: #666666">=</span>NF-2 <span style="color: #AA22FF; font-weight: bold">for</span><span style="color: #666666">(</span><span style="color: #B8860B">i</span><span style="color: #666666">=</span>1; i<<span style="color: #666666">=</span>N2; i++<span style="color: #666666">)</span> G2<span style="color: #666666">[</span>i<span style="color: #666666">]=</span><span style="color: #AA22FF; font-weight: bold">$(</span>i+2<span style="color: #AA22FF; font-weight: bold">)</span> <span style="color: #666666">}</span> END <span style="color: #666666">{</span> print <span style="color: #BB4444">"[ "</span>Grp1<span style="color: #BB4444">"_"</span>Grp2<span style="color: #BB4444">" ]"</span> <span style="color: #AA22FF; font-weight: bold">for</span><span style="color: #666666">(</span><span style="color: #B8860B">i</span><span style="color: #666666">=</span>1; i<<span style="color: #666666">=</span>N1; i++<span style="color: #666666">)</span> <span style="color: #666666">{</span> <span style="color: #AA22FF; font-weight: bold">for</span><span style="color: #666666">(</span><span style="color: #B8860B">j</span><span style="color: #666666">=</span>1; j<<span style="color: #666666">=</span>N2; j++<span style="color: #666666">)</span> <span style="color: #AA22FF">printf</span> <span style="color: #BB4444">"%d %d "</span>, G1<span style="color: #666666">[</span>i<span style="color: #666666">]</span>, G2<span style="color: #666666">[</span>j<span style="color: #666666">]</span> print <span style="color: #BB4444">""</span> <span style="color: #666666">}</span> <span style="color: #666666">}</span> <span style="color: #BB4444">'</span> <span style="color: #B8860B">$File</span>.ndx >> <span style="color: #B8860B">$File</span>.ndx </pre></div> </td></tr></table>运行脚本, 指定输出文件名称和两个组的名称, 这段代码会生成两个组的原子对组合, 并将其命名为一个新组追加到原来的索引文件中. 然后运行gmx distance -s -f -n -oav -oall
, 选择这个新组, 就可以得到所要的距离文件了. 值得注意的是, 组中的原子对数目最好不要太多, 否则GROMACS运行时所需的内存太多, 可能导致失败.
使用这种模式计算原子之间的距离很简单, 但要想计算两个组的质心之间的距离就有点麻烦, 需要利用选区语法来完成. 例如我们要计算残基1-4与残基7-9质心之间的距离, 可以使用下面的方式:
gmx distance -s -f -select "com of resnr 1 to 4 plus com of resnr 7 to 9" -oav -oall
其中的选区语法请参考GROMACS选区(selection)语法及用法.