使用Gnuplot绘制红外光谱图

5

我有一个红外光谱,想要绘制出感兴趣化合物的频谱图。我拥有一个名为 spectrum.dat 的文件,其中包含所有数据点,格式如下:

    # X  Y     
    300  100
    301  100
    302   99
    303   70
    ...
    3999  98
    4000 100

我想使用典型的红外光谱X轴绘制这个图表,但是我在这方面有困难。如果您不熟悉,这是典型的红外光谱的样子(除了图表本身的标签)。请注意,X轴被反转,并且在2000单位(倒数厘米)以上突然加倍。有没有办法强制Gnuplot以这种方式绘制我的数据?到目前为止,我已经想出了以下脚本:
    # Make an SVG of size 800x500
    set terminal svg size 800,500 fname 'CMU Sans Serif' fsize '10'
    set output 'ir.svg'
    # Color definitions
    set border linewidth 1.5
    set style line 1 lc rgb '#a0a0a0' lt 1 lw 2 pt 7 # gray
    # Format graph
    unset key
    set xlabel 'Wavenumbers'
    set ylabel 'Transmittance'
    set xrange [4000:300]
    # Plot data
    plot 'spectrum.dat' with lines ls 1

这样可以很好地反转x轴,但我无法想出如何以这种不寻常的方式改变比例尺。

如果您使用set link并且开发版本的gnuplot是可选项,请参阅gnuplot:如何设置自定义非线性比例尺。即将推出的gnuplot 5.0版本现在甚至有 - Christoph
2个回答

6
作为一名化学家,我有动力回答...
据我所知,gnuplot不容易实现任意坐标轴缩放(除非有人对如何使用“set link”有想法)。在这种情况下,我的策略是将两个部分分别绘制并无缝连接:
#!/usr/bin/env gnuplot

set terminal png size 800,500
set output 'ir.png'

set xlabel 'Wavenumbers' offset 20
set ylabel 'Transmittance'

set tics out nomirror

set key bottom right

set bmargin 4

set yrange [0:1]

set multiplot layout 1,2 title 'IR Spectrum of Cholesterol'

# left half of plot
set xrange [4000:2000]
set rmargin 0
set border 7
plot 'cholesterol.txt' notitle

# right half of plot
set xrange [1999:300]
set lmargin 0
set rmargin 2
set border 13

unset xlabel
unset ylabel
unset ytics

plot 'cholesterol.txt' title 'Cholesterol'

unset multiplot

我的一个小问题是 2000 写了两遍,在我的屏幕上看起来更加粗体,但是我会让你自己调整。 输入图片描述

5
andyras的回答非常好,以下是一种在布局选项方面更简单(更优雅:-P)的解决方案。这也应该是一种更通用的解决方案。如果刻度线不太多(如果刻度线太多,请参见下图),则可以通过将曲线本身缩放到2000以上,然后手动添加所有刻度线来完成。由于我没有可用的红外光谱数据,因此我将使用虚拟文件“+”并从4000到500绘制log(x):
xmax=4000 ; xmin = 500
pivot = 2000 ; rescfactor = 2.
rescale(x) = (x >= pivot ? x : pivot + rescfactor*(x-pivot))
set xrange [rescale(xmax):rescale(xmin)]
set xtics ("4000" 4000, "3000" 3000, "2000" 2000, \
"1500" rescale(1500), "1000" rescale(1000), "500" rescale(500))
plot "+" u (rescale($1)):(log($1)) w l

enter image description here

在您的情况下,您只需将log($1)替换为2或任何您正在绘制的东西。

在较新版本的gnuplot(从4.4开始)中,使用循环可以自动添加刻度:

xmax = 4000 ; xmin = 500 ; step = 500
set xtics (sprintf("%i",xmax) rescale(xmax)) # Add the first tic by hand
set for [i=xmin:xmax-step:step] xtics add (sprintf("%i",i) rescale(i))

从gnuplot 4.6开始,还可以使用 do for 构造不同的 for

do for [i=xmin:xmax-step:step] {set xtics add (sprintf("%i",i) rescale(i))}

1
很好的答案,我可能会做一个改变,即定义 pivot=2000; rescale(x) = ($1 >= pivot ? $1 : pivot + 2.*($1-pivot)) 这样你就可以在所有量上调用该函数。 - andyras
@andyras 已更改,我还添加了一个重新缩放因子。有趣的是,今天在工作中我需要使用这个解决方案来处理完全不相关的事情... - Miguel
2
如果您将xtics的迭代更改为使用set for,它也适用于4.4版本:set for [i=xmin:xmax-step:step] xtics add (sprintf("%i",i) rescale(i))。只有do for结构是在4.6版本中引入的。 - Christoph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接