写在前面
本文是在实验过程中进行简单数据处理时,使用的部分画图程序,涉及折线图、散点图、直方图。所用数据均保存在txt文档中。在函数使用过程中也曾遇到问题,这里的程序是测试可用的, 或可作为借鉴。
环境
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from scipy.optimize import curve_fit as cf
import matplotlib.ticker as ticker
折线图和图中箭头
数据读取
path = 'D:/python_result/Calibration/'
inch3 = open(path + '3-inch.txt')
font = {'weight': 'normal', 'size': 30} # 字体
inch3.readline().split()
用到的数据在txt文档里按行存储,一行是一组数据,并且每相邻两行数据是一样的。
['0.378375',
'0.3795',
'0.3840625',
'0.3799375',
'0.364625',
'0.358625',
'0.34175',
'0.339125',
'0.3423125',
'0.353',
'0.3696875']
画图
画图过程简单,只是选取数据plot就好
x = [0, -7, -24, -40, -50, -59.5, -70, -80, -108.2, -131.8, -146.8]
label = [20, 13, -4, -20, -30, -39.5, -50, -50, -21.8, 1.8, 16.8]
fig = plt.figure(figsize=(20, 12))
ax = fig.add_subplot(1, 1, 1)
for tmp in inch3.readlines():
tmp = list(map(float, tmp.split()))
if i % 2 == 0:
plt.plot(x, tmp, linewidth=1.5, marker='o', markersize=10)
i += 1
plt.plot([-70, -70], [-0.5, 1.1], color='blue', linewidth=2.5, linestyle='--')
plt.plot([-80, -80], [-0.5, 1.1], color='red', linewidth=2.5, linestyle='--')
这是调整参数之前的效果,可以看出来x,y轴的范围以及坐标轴上ticks的大小都要调整
设置图像参数
参数实际上是在图已经画出来之后调整的,依据需要的效果
ax.set_xlabel(r'$^\circ$C', font) # x轴label,font是之前声明的字体属性
ax.set_ylabel(r'Gain of 3-inch PMTs ($1\times10^7$)', font) # y轴label
plt.tick_params(labelsize=30) # 坐标轴ticks的字体大小
plt.grid(linestyle='--') # figure中的网格线
plt.xlim(5, -150) # x轴范围
plt.ylim(0.2, 0.85) # y轴范围
plt.xticks(x, label) # 修改x轴的ticks
这是调整参数之后的效果
根据需要在图中添加箭头
为了更好的说明图中展示的数据,需要在其中加上箭头以及文字说明,用到的是matplotlib.pyplot.annotate函数,可以点击查看其参数说明。不过使用过程中发现,xytext参数,也就是设置文本显示坐标的参数,其坐标单位和图中的坐标并不匹配,因此是不断修改尝试而得到想要的结果的。
ax.annotate('Cooling process', xy=(-70, 0.506),
xytext=(0.25, 0.45), textcoords='axes fraction',
arrowprops=dict(facecolor='blue', shrink=0.05),
fontsize=25,
horizontalalignment='center', verticalalignment='bottom')
ax.annotate('', xy=(-18, 0.506),
xytext=(0, 0.47), textcoords='axes fraction',
arrowprops=dict(facecolor='blue', shrink=0.05),
fontsize=25,
horizontalalignment='center', verticalalignment='bottom')
ax.annotate('Heating process', xy=(-150, 0.506),
xytext=(0.75, 0.45), textcoords='axes fraction',
arrowprops=dict(facecolor='red', shrink=0.05),
fontsize=25,
horizontalalignment='center', verticalalignment='bottom')
ax.annotate('', xy=(-96, 0.506),
xytext=(0.55, 0.47), textcoords='axes fraction',
arrowprops=dict(facecolor='red', shrink=0.05),
fontsize=25,
horizontalalignment='center', verticalalignment='bottom')
加上箭头以及文字说明的效果
至此完成。
散点图
数据读取
path = 'D:/python_result/'
hv1_1 = np.loadtxt(path + 'HV1_1.txt', encoding='utf-8', delimiter='\t')
hv2_1 = np.loadtxt(path + 'HV2_1.txt', encoding='utf-8', delimiter='\t')
hv3_1 = np.loadtxt(path + 'HV3_1.txt', encoding='utf-8', delimiter='\t')
date = np.loadtxt(path + 'Date_1.txt', encoding='utf-8', delimiter='\t', dtype=str).astype(str)
font = {'weight': 'normal', 'size': 30} # 字体
hv1_1长这样
date长这样
画图
散点图选择数据scatter就好
fig = plt.figure(figsize=(20, 12))
ax = fig.add_subplot(1, 1, 1)
ax.scatter(date, hv1_1, s=30, c='r', marker='.', label='PMTID 80010', linewidth=3)
ax.scatter(date, hv2_1, s=30, c='b', marker='.', label='PMTID 80061', linewidth=3)
ax.scatter(date, hv3_1, s=30, c='k', marker='.', label='PMTID 80064', linewidth=3)
此时的图长这样,横坐标是日期信息,太密了,什么都看不出来,并且有三组信息但是缺少legend,还有坐标轴范围和ticks的字体大小需要调整
设置图像参数
将之前的图像添加了坐标轴的label、网格线、legend,并修改了坐标轴范围、坐标轴ticks的字体大小和横坐标的疏密度
ax.set_xlabel('Date', font)
ax.set_ylabel('HV / V', font)
plt.tick_params(labelsize=30)
ax.xaxis.set_major_locator(ticker.MultipleLocator(68)) # 用来修改横坐标的疏密度
plt.legend(prop=font, loc='upper right')
plt.ylim(900, 1350)
plt.grid(linestyle='--')
此时的样子
直方图和拟合
数据获取
这里的直方图使用的数据和前面的散点图是同样的
path = 'D:/python_result/'
hv1_1 = np.loadtxt(path + 'HV1_1.txt', encoding='utf-8', delimiter='\t')
hv2_1 = np.loadtxt(path + 'HV2_1.txt', encoding='utf-8', delimiter='\t')
hv3_1 = np.loadtxt(path + 'HV3_1.txt', encoding='utf-8', delimiter='\t')
date = np.loadtxt(path + 'Date_1.txt', encoding='utf-8', delimiter='\t', dtype=str).astype(str)
画图
使用hist画图
fig = plt.figure(figsize=(20, 12))
ax = fig.add_subplot(1, 1, 1)
mu = np.mean(hv1_1)
sigma = np.std(hv1_1)
par1 = ax.hist(hv1_1, **params, color='r', label='$\mathrm{PMTID\ 80010}$\n$Mean=%.1f$\n$RMS=%.1f$' % (mu, sigma),
linewidth=5, range=(1000, 1300))
此时的直方图中,没有legend,没有坐标轴label,坐标轴ticks字体大小不够,并且还为做拟合。
设置图像参数
添加坐标轴label,修改坐标轴ticks字体大小
ax.set_xlabel('HV / V', font)
ax.set_ylabel('Counts', font)
plt.tick_params(labelsize=30)
拟合并绘制拟合图像
使用的拟合函数是高斯函数
def gaussian(x, *param):
return param[0]*np.exp(-np.power(x - param[1], 2.) / (2 * np.power(param[2], 2.)))
拟合并获得拟合得到的参数,绘制拟合结果,添加legend。
x = np.linspace(mu - 50, mu + 50, 1000)
# curve_fit的返回值中para是拟合参数,pco是方差-协方差矩阵,可以通过对pco的对角元开方得到拟合参数的标准差作为拟合误差
para, pco = cf(gaussian, par1[1][0: len(par1[0])], par1[0], p0=[70, mu, sigma])
mu = para[1]
sigma = para[2]
plt.legend(labels=['$\mathrm{PMTID\ 80010}$\n$\mu=%.1f$\n$\sigma=%.1f$' % (mu, sigma)], prop=font)
plt.plot(x, gaussian(x, *para), color='orange', linewidth=3)