layout: post title: xvg曲线中心移动平均平滑脚本 categories:
在查看GROMACS分析程序生成的xvg文件时, 有时候曲线不够平滑, 上下波动很厉害. 为美观或其他目的有时候需要对曲线进行平滑. 常见的绘图软件一般都支持曲线平滑, 可选方法也很多. 其中最简单的是移动平均算法(moving average). 但简单的移动平均算法平滑出来的曲线存在滞后性, 对于有峰和谷的曲线不适合. 一个解决方法是采用基于中心点的移动平均算法. 简单地说, 每个点的平滑值是其自身及前后若干点数值的平均值. 下面这段脚本专门用于xvg文件的平滑, 供需要的人参考.
<table class="highlighttable"><th colspan="2" style="text-align:left">gmx_smxvg.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 35 36 37 38 39 40 41 42 43 44 45 46</pre></div></td><td class="code"><div class="highlight" style="background: #f8f8f8"><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: #bbbbbb"></span> <span style="color: #BB4444">>>>>>>>>>>>>>>>></span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">gmx_smxvg</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444"><<<<<<<<<<<<<<<<</span><span style="color: #bbbbbb"></span> <span style="color: #BB4444">>>>>>>>>>>>>>>>></span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">Jicun</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">Li</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444"><<<<<<<<<<<<<<<<</span><span style="color: #bbbbbb"></span> <span style="color: #BB4444">>>>>>>>>>>>></span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">2017-05-10</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">14:44:21</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444"><<<<<<<<<<<<</span><span style="color: #bbbbbb"></span> <span style="color: #BB4444">>></span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">Usage:</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">gmx_smxvg</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">{-n</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">5}</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">{-col</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">2}</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444"><File.xvg...></span><span style="color: #bbbbbb"></span> <span style="color: #BB4444">>></span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">-n:</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">Number</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">of</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">Points</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">to</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">Run</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">Smoothing</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">Average,</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">Shoule</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">be</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">ODD</span><span style="color: #bbbbbb"></span> <span style="color: #BB4444">>></span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">-c:</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">Column</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">Number</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">of</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">the</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">Data</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">to</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">Smooth"</span><span style="color: #bbbbbb"></span> <span style="color: #666666">[[</span><span style="color: #bbbbbb"> </span><span style="color: #B8860B">$#</span><span style="color: #bbbbbb"> </span>-lt<span style="color: #bbbbbb"> </span><span style="color: #666666">1</span><span style="color: #bbbbbb"> </span><span style="color: #666666">]]</span><span style="color: #bbbbbb"> </span><span style="color: #666666">&&</span><span style="color: #bbbbbb"> </span><span style="color: #666666">{</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF">echo</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">"</span><span style="color: #B8860B">$usage</span><span style="color: #BB4444">"</span>;<span style="color: #bbbbbb"> </span>exit;<span style="color: #bbbbbb"> </span><span style="color: #666666">}</span><span style="color: #bbbbbb"></span> <span style="color: #B8860B">pnt</span><span style="color: #666666">=</span>5;<span style="color: #bbbbbb"> </span><span style="color: #B8860B">col</span><span style="color: #666666">=</span>2<span style="color: #bbbbbb"></span> <span style="color: #B8860B">opt</span><span style="color: #666666">=(</span><span style="color: #B8860B">$@</span><span style="color: #666666">)</span>;<span style="color: #bbbbbb"> </span><span style="color: #B8860B">N</span><span style="color: #666666">=</span><span style="color: #BB6688; font-weight: bold">${#</span><span style="color: #B8860B">opt</span>[@]<span style="color: #BB6688; font-weight: bold">}</span><span style="color: #bbbbbb"></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>0;<span style="color: #bbbbbb"> </span>i<N;<span style="color: #bbbbbb"> </span>i++<span style="color: #666666">))</span>;<span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">do</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span><span style="color: #B8860B">arg</span><span style="color: #666666">=</span><span style="color: #BB6688; font-weight: bold">${</span><span style="color: #B8860B">opt</span>[<span style="color: #B8860B">$i</span>]<span style="color: #BB6688; font-weight: bold">}</span>;<span style="color: #bbbbbb"> </span><span style="color: #B8860B">j</span><span style="color: #666666">=</span><span style="color: #AA22FF; font-weight: bold">$((</span>i+1<span style="color: #AA22FF; font-weight: bold">))</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span><span style="color: #666666">[[</span><span style="color: #bbbbbb"> </span><span style="color: #B8860B">$arg</span><span style="color: #bbbbbb"> </span><span style="color: #666666">=</span>~<span style="color: #bbbbbb"> </span>-n<span style="color: #bbbbbb"> </span><span style="color: #666666">]]</span><span style="color: #bbbbbb"> </span><span style="color: #666666">&&</span><span style="color: #bbbbbb"> </span><span style="color: #666666">{</span><span style="color: #bbbbbb"> </span><span style="color: #B8860B">pnt</span><span style="color: #666666">=</span><span style="color: #BB6688; font-weight: bold">${</span><span style="color: #B8860B">opt</span>[<span style="color: #B8860B">$j</span>]<span style="color: #BB6688; font-weight: bold">}</span>;<span style="color: #bbbbbb"> </span>opt<span style="color: #666666">[</span><span style="color: #B8860B">$i</span><span style="color: #666666">]=</span><span style="color: #BB4444">""</span>;<span style="color: #bbbbbb"> </span>opt<span style="color: #666666">[</span><span style="color: #B8860B">$j</span><span style="color: #666666">]=</span><span style="color: #BB4444">""</span>;<span style="color: #bbbbbb"> </span><span style="color: #666666">}</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span><span style="color: #666666">[[</span><span style="color: #bbbbbb"> </span><span style="color: #B8860B">$arg</span><span style="color: #bbbbbb"> </span><span style="color: #666666">=</span>~<span style="color: #bbbbbb"> </span>-c<span style="color: #bbbbbb"> </span><span style="color: #666666">]]</span><span style="color: #bbbbbb"> </span><span style="color: #666666">&&</span><span style="color: #bbbbbb"> </span><span style="color: #666666">{</span><span style="color: #bbbbbb"> </span><span style="color: #B8860B">col</span><span style="color: #666666">=</span><span style="color: #BB6688; font-weight: bold">${</span><span style="color: #B8860B">opt</span>[<span style="color: #B8860B">$j</span>]<span style="color: #BB6688; font-weight: bold">}</span>;<span style="color: #bbbbbb"> </span>opt<span style="color: #666666">[</span><span style="color: #B8860B">$i</span><span style="color: #666666">]=</span><span style="color: #BB4444">""</span>;<span style="color: #bbbbbb"> </span>opt<span style="color: #666666">[</span><span style="color: #B8860B">$j</span><span style="color: #666666">]=</span><span style="color: #BB4444">""</span>;<span style="color: #bbbbbb"> </span><span style="color: #666666">}</span><span style="color: #bbbbbb"></span> <span style="color: #AA22FF; font-weight: bold">done</span><span style="color: #bbbbbb"></span> <span style="color: #666666">[[</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">$((</span>pnt%2<span style="color: #AA22FF; font-weight: bold">))</span><span style="color: #bbbbbb"> </span>-eq<span style="color: #bbbbbb"> </span><span style="color: #666666">0</span><span style="color: #bbbbbb"> </span><span style="color: #666666">]]</span><span style="color: #bbbbbb"> </span><span style="color: #666666">&&</span><span style="color: #bbbbbb"> </span><span style="color: #666666">{</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF">echo</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">'</span>ERROR!!!<span style="color: #bbbbbb"> </span>Number<span style="color: #bbbbbb"> </span>of<span style="color: #bbbbbb"> </span>Points<span style="color: #bbbbbb"> </span>should<span style="color: #bbbbbb"> </span>be<span style="color: #bbbbbb"> </span>ODD!<span style="color: #BB4444">'</span>;<span style="color: #bbbbbb"> </span>exit;<span style="color: #bbbbbb"> </span><span style="color: #666666">}</span><span style="color: #bbbbbb"></span> <span style="color: #AA22FF; font-weight: bold">for</span><span style="color: #bbbbbb"> </span>file<span style="color: #bbbbbb"> </span>in<span style="color: #bbbbbb"> </span><span style="color: #BB6688; font-weight: bold">${</span><span style="color: #B8860B">opt</span>[@]<span style="color: #BB6688; font-weight: bold">}</span>;<span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">do</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span>awk<span style="color: #bbbbbb"> </span>-v<span style="color: #bbbbbb"> </span><span style="color: #B8860B">pnt</span><span style="color: #666666">=</span><span style="color: #B8860B">$pnt</span><span style="color: #bbbbbb"> </span>-v<span style="color: #bbbbbb"> </span><span style="color: #B8860B">col</span><span style="color: #666666">=</span><span style="color: #B8860B">$col</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">'</span><span style="color: #bbbbbb"> </span><span style="color: #BB6622; font-weight: bold">\</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span>/^<span style="color: #666666">[</span><span style="color: #008800; font-style: italic">#@]/</span><span style="color: #bbbbbb"> </span><span style="color: #008800; font-style: italic">{print;</span><span style="color: #bbbbbb"> </span><span style="color: #008800; font-style: italic">next}</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span>/^<span style="color: #666666">[</span>^#@<span style="color: #666666">]</span>/<span style="color: #bbbbbb"> </span><span style="color: #666666">{</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span>n++;<span style="color: #bbbbbb"> </span><span style="color: #B8860B">j</span><span style="color: #666666">=</span>n%pnt<span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">if</span><span style="color: #666666">(</span>n<pnt<span style="color: #666666">)</span><span style="color: #bbbbbb"> </span><span style="color: #666666">{</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span>sma<span style="color: #bbbbbb"> </span>+<span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #B8860B">$col</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">if</span><span style="color: #666666">(</span>n<<span style="color: #666666">(</span>pnt+1<span style="color: #666666">)</span>/2<span style="color: #666666">)</span><span style="color: #bbbbbb"> </span><span style="color: #666666">{</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </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;<span style="color: #bbbbbb"> </span>i<<span style="color: #666666">=</span>col;<span style="color: #bbbbbb"> </span>i++<span style="color: #666666">)</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF">printf</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">"%12.6f"</span>,<span style="color: #bbbbbb"> </span><span style="color: #B8860B">$i</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span><span style="color: #AA22FF">printf</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">"%12.6f"</span>,<span style="color: #bbbbbb"> </span>sma/n<span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </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>col+1;<span style="color: #bbbbbb"> </span>i<<span style="color: #666666">=</span>NF;<span style="color: #bbbbbb"> </span>i++<span style="color: #666666">)</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF">printf</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">"%12.6f"</span>,<span style="color: #bbbbbb"> </span><span style="color: #B8860B">$i</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span>print<span style="color: #bbbbbb"> </span><span style="color: #BB4444">""</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span><span style="color: #666666">}</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span><span style="color: #666666">}</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF; font-weight: bold">else</span><span style="color: #bbbbbb"> </span><span style="color: #666666">{</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span>sma<span style="color: #bbbbbb"> </span>+<span style="color: #666666">=</span><span style="color: #bbbbbb"> </span><span style="color: #B8860B">$col</span>-f<span style="color: #666666">[</span>j<span style="color: #666666">]</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span><span style="color: #B8860B">now</span><span style="color: #666666">=(</span>n-<span style="color: #666666">(</span>pnt-1<span style="color: #666666">)</span>/2<span style="color: #666666">)</span>%pnt<span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span>split<span style="color: #666666">(</span>txt<span style="color: #666666">[</span>now<span style="color: #666666">]</span>,<span style="color: #bbbbbb"> </span>dat<span style="color: #666666">)</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span><span style="color: #AA22FF">printf</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">"%12.6f"</span>,<span style="color: #bbbbbb"> </span>dat<span style="color: #666666">[</span>1<span style="color: #666666">]</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </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>2;<span style="color: #bbbbbb"> </span>i<<span style="color: #666666">=</span>col;<span style="color: #bbbbbb"> </span>i++<span style="color: #666666">)</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF">printf</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">"%12.6f"</span>,<span style="color: #bbbbbb"> </span>dat<span style="color: #666666">[</span>i<span style="color: #666666">]</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span><span style="color: #AA22FF">printf</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">"%12.6f"</span>,<span style="color: #bbbbbb"> </span>sma/pnt<span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </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>col+1;<span style="color: #bbbbbb"> </span>i<<span style="color: #666666">=</span>NF;<span style="color: #bbbbbb"> </span>i++<span style="color: #666666">)</span><span style="color: #bbbbbb"> </span><span style="color: #AA22FF">printf</span><span style="color: #bbbbbb"> </span><span style="color: #BB4444">"%12.6f"</span>,<span style="color: #bbbbbb"> </span>dat<span style="color: #666666">[</span>i<span style="color: #666666">]</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span>print<span style="color: #bbbbbb"> </span><span style="color: #BB4444">""</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span><span style="color: #666666">}</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span>f<span style="color: #666666">[</span>j<span style="color: #666666">]=</span><span style="color: #B8860B">$col</span>;<span style="color: #bbbbbb"> </span>txt<span style="color: #666666">[</span>j<span style="color: #666666">]=</span><span style="color: #B8860B">$0</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span><span style="color: #666666">}</span><span style="color: #bbbbbb"></span> <span style="color: #bbbbbb"> </span><span style="color: #BB4444">'</span><span style="color: #bbbbbb"> </span><span style="color: #B8860B">$file</span><span style="color: #bbbbbb"> </span>><span style="color: #BB6688; font-weight: bold">${</span><span style="color: #B8860B">file</span>%.xvg<span style="color: #BB6688; font-weight: bold">}</span>~sm.xvg<span style="color: #bbbbbb"></span> <span style="color: #AA22FF; font-weight: bold">done</span><span style="color: #bbbbbb"></span> </pre></div> </td></tr></table>脚本支持两个选项:
-n
指定平滑时所用的点数, 必须是奇数. 默认为-n 5
, 表示使用数据点及其前后两点的平均值作为平滑值. 点数越大, 平滑后曲线越光滑.
-c
指定平滑数据所在的列编号. 默认为-c 2
, 表示平滑xvg文件的第2列数据.
原始数据及其平滑后的数据会另写入原文件名~sm.xvg
文件中. 其中第n列数据的平滑值会添加到n+1列中.
下图是一个简单的例子