在Python中用多个x轴重叠绘制数据
我正在尝试从一个 .fits 文件中绘制一些数据,这个文件包含了计数率和时间的信息。我的目标是把不同事件的计数率绘制在同一个图上,并且在三个不同的 x 轴上显示不同的时间。
因为我想绘制的事件是周期性的,所以我对识别正确的时间设置了一些条件,这样我就可以只提取我需要的时间范围内的计数率。
#!/usr/bin/env python
from scipy import *
from numpy import *
from pylab import *
from scipy import optimize
import pyfits, os, re, glob
import matplotlib.pyplot as plt
import matplotlib as mpl
from matplotlib.ticker import FuncFormatter
rc('font',**{'family':'serif','serif':['Helvetica']})
rc('ps',usedistiller='xpdf')
rc('text', usetex=True)
#------------------------------------------------------
tmin=56200
tmax=56249
data=pyfits.open('http://heasarc.gsfc.nasa.gov/docs/swift/results/transients/weak/GX304-1.orbit.lc.fits')
time = data[1].data.field(0)/86400. + data[1].header['MJDREFF'] + data[1].header['MJDREFI']
rate = data[1].data.field(1)
error = data[1].data.field(2)
data.close()
cond= ((time > tmin-5) & (time < tmax)) | ((time + 132.5 > tmin) & (time + 132.5 < tmax-10)) | ((time + 265 > tmin) & (time + 265 < tmax-12))
time=time[cond]
rate=rate[cond]
error=error[cond]
fig, ax1 = plt.subplots()
newax2 = ax1.twiny()
newax3 = ax1.twiny()
# Make some room at the bottom
fig.subplots_adjust(bottom=0.30)
newax2.set_frame_on(True)
newax2.patch.set_visible(False)
newax2.xaxis.set_ticks_position('bottom')
newax2.xaxis.set_label_position('bottom')
newax2.spines['bottom'].set_position(('outward', 20))
newax3.set_frame_on(True)
newax3.patch.set_visible(False)
newax3.xaxis.set_ticks_position('bottom')
newax3.xaxis.set_label_position('bottom')
newax3.spines['bottom'].set_position(('outward', 40))
#..plot the current light curve
errorbar(time, rate, error, fmt='r.', capsize=0)
gca().xaxis.set_major_formatter(FormatStrFormatter('%5.1f'))
#..overplot a previous outburst
errorbar(time + 122.5, rate, error, fmt='g.', capsize=0)
errorbar(time + 255, rate, error, fmt='k.', capsize=0)
axis([tmin-10,tmax,-0.00,0.45])
xlabel('Time, MJD')
ylabel("BAT cts/s/cm$^2$")
savefig("sync.eps",orientation='portrait',papertype='a4',format='eps')
os.system('gv sync.eps')
我正在绘制三个事件,所以我需要三个 x 轴;不过,如果可能的话,我希望在 x 轴上用对应的颜色写上相应的时间。底部的时间是红色曲线的正确时间,也就是最近的事件。
请问有什么建议吗?非常感谢!
1 个回答
0
如果我理解你的问题没错,问题出在第一和第二个x轴的刻度不正确上。你只需要把errorbar
函数绑定到正确的轴上,matplotlib就会帮你自动调整比例。像这样:
...
#..plot the current light curve
ax1.errorbar(time, rate, error, fmt='r.', capsize=0)
gca().xaxis.set_major_formatter(FormatStrFormatter('%5.1f'))
#..overplot a previous outburst
newax2.errorbar(time + 122.5, rate, error, fmt='g.', capsize=0)
newax3.errorbar(time + 255, rate, error, fmt='k.', capsize=0)
...
其实我更喜欢在matplotlib中使用面向对象的方法,所以这样做是唯一的选择。
如果你不介意的话,我会把颜色的部分留给我评论中的参考。
更新
下面是一些更新后的代码,也许这正是你想要的。诀窍在于不要移动x数据(time
),而是简单地调整x轴的范围(你所查看的“窗口”)到你想要的值。所以我分别对每个轴的x范围应用了122.5和255的偏移(反向)。
我还需要为每个轴单独设置格式化器;如果不设置格式化器,你会得到类似于偏移表示法(0 .. 10 .. 20 .. 30 + 56190)的结果。像你之前那样使用全局格式化器,我觉得只对ax1
有效。请注意,我只全局设置了y轴的范围,注释掉了axis
命令。
...
##..plot the current light curve
ax1.errorbar(time, rate, error, fmt='r.', capsize=0)
ax1.set_xlim(tmin-10,tmax)
ax1.xaxis.set_major_formatter(FormatStrFormatter('%5.1f'))
##..overplot a previous outburst
newax2.errorbar(time, rate, error, fmt='g.', capsize=0)
newax3.errorbar(time, rate, error, fmt='k.', capsize=0)
newax2.set_xlim(tmin-10-122.5,tmax-122.5)
newax2.xaxis.set_major_formatter(FormatStrFormatter('%5.1f'))
newax3.set_xlim(tmin-10-255,tmax-255)
newax3.xaxis.set_major_formatter(FormatStrFormatter('%5.1f'))
ylim(0,0.45)
#axis([tmin-10,tmax,-0.00,0.45])
...
这样就得到了
这和你原来的脚本生成的结果相似,但希望x轴的刻度是正确的(除了颜色部分)。