Python拟合吸附等温线并计算吸附焓

前一阵子帮人用C++写了一个用以计算吸附焓的简单小程序,仅实现了得到吸附等温线方程后计算吸附焓的功能。最近重拾Python语言,在尝试了Python的各类库之后对其爱不释手。遂尝试着将这个程序用Python完善了一下,实现了数据读入,拟合,计算吸附焓一系列流程。

作为一个新手,写程序的过程依然很揪心。好在换用了Anaconda后的Jupyter Notebook十分友好,可以在每个cell中直接运行查看结果进行调试。在经历了不断地与错误信息斗争后,终于磕磕绊绊地将想要的功能实现了。所以在这里记录一下学习到的一些语法知识以及程序目前的缺陷。

程序内容

#拟合BET数据中的吸附曲线并计算吸附焓
#Version 2.00
#以实现对数据的读取,转化单位和langmuir方程拟合并做图
#对BET软件直接生成的xls文件尚不能直接打开,需要另存为xlsx格式
#Author: lewisbase
#Date: 2019.04.08

import csv
import math
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import ticker
from matplotlib import rcParams
from scipy.optimize import leastsq

GRID=30000
R=8.314510e-3
###############################################################################################

def Langmuir(c):
    b=c
    return y-qmax*b*x/(1+b*x)
def Langmuirfit(x):
    return qmax*b*x/(1+b*x)
def Freundlich(f):
    k,l=f
    return y-k*x**(1/l)
def Freundlichfit(x):
    return k*x**(1/l)

###############################################################################################

print("Welcome to absorption calculator! Please follow the hinds and input the right message.")
ifheat=input("Would you like to caiculate the heat of absorption?(Y/N)")
if ifheat == "Y" or ifheat == "y":
    T1=input("Input the first temperature:\n")
    filename1=input("Input the filename of T1:\n")
    T2=input("Input the second temperature:\n")
    filename2=input("Input the filename of T2:\n")
    read1=pd.read_excel(filename1,usecols="L,M",header=None,convert_float=True,dtype=float,skiprows=28)
    read1=np.array(read1,dtype=float)
    x1=np.array([])
    for x in read1[:,0]:
        if not np.isnan(x):
            #print(x)
            x1=np.append(x1,x)
    y1=np.array([])
    for y in read1[:,1]:
        if not np.isnan(y):
            #print(y)
            y1=np.append(y1,y)
    read2=pd.read_excel(filename2,usecols="L,M",header=None,convert_float=True,dtype=float,skiprows=28)
    read2=np.array(read1,dtype=float)
    x2=np.array([])
    for xbuff in read2[:,0]:
        if not np.isnan(xbuff):
            #print(x)
            x2=np.append(x2,xbuff)
    y2=np.array([])
    for ybuff in read2[:,1]:
        if not np.isnan(ybuff):
            #print(y)
            y2=np.append(y2,ybuff)
    x1*=101.325
    x2*=101.325
else:
    T1=input("Input the temperature:\n")
    filename1=input("Input the filename:\n")
    read1=pd.read_excel(filename1,usecols="L,M",header=None,dtype=float,skiprows=28)
    read1=np.array(read1,dtype=float)
    x1=np.array([])
    for xbuff in read1[:,0]:
        if not np.isnan(xbuff):
            #print(x)
            x1=np.append(x1,xbuff)
    y1=np.array([])
    for ybuff in read1[:,1]:
        if not np.isnan(ybuff):
            #print(y)
            y1=np.append(y1,ybuff)
    x1*=101.325
print(x1)
print(y1)

#####################################################################################################

print("Please choose the absorption model you want to use: 1. Langmuir; 2. Freundlich\n")
model=int(input("Input the number: \n"))
while model!=1 and model!=2:
    print("Sorry, this program currently only supports the above two models. Please input 1 or 2.")
    model=int(input("Input the number: \n"))
if model==1:
    print("You choose the Langmuir model, mission start!\n")
    qmax=np.max(y1)
    x=x1
    y=y1
    result1=leastsq(Langmuir,[1])
    a1=result1[0]
    #aerr1,berr1=result1[1]
    xfit1=np.linspace(0,np.max(x1),GRID,endpoint=True)
    b=a1
    yfit1=np.array([])
    for x in xfit1:
        yfit1=np.append(yfit1,Langmuirfit(x))
    print("The fit coefficient at {0} is: ".format(T1),a1)#,aerr1,berr1)
    if ifheat == "Y" or ifheat == "y":
        qmax=np.max(y2)
        x=x2
        y=y2
        result2=leastsq(Langmuir,[1])
        a2=result1[0]
        #aerr2,berr2=result2[1]
        xfit2=np.linspace(0,np.max(x2),GRID,endpoint=True)
        b=a2
        yfit2=np.array([])
        for x in xfit2:
            yfit2=np.append(yfit2,Langmuirfit(x))
        print("The fit coefficient at {0} is: ".format(T2),a2)#,aerr2,berr2)
elif model==2:
    print("You choose the Freundlich model, mission start!\n")
    x=x1
    y=y1
    result1=leastsq(Freundlich,[1,1])
    a1,b1=result1[0]
    #aerr1,berr1=result1[1]
    xfit1=np.linspace(0,np.max(x1),GRID,endpoint=True)
    k=a1
    l=b1
    yfit1=np.array([])
    for x in xfit1:
        yfit1=np.append(yfit1,Freundlichfit(x))
    print("The fit coefficient at {0} is: ".format(T1),a1,b1)#,aerr1,berr1)
    if ifheat == "Y" or ifheat == "y":
        x=x2
        y=y2
        result2=leastsq(Freundlich,[1,1])
        a2,b2=result1[0]
        #aerr2,berr2=result2[1]
        xfit2=np.linspace(0,np.max(x2),GRID,endpoint=True)
        k=a2
        l=b2
        yfit2=np.array([])
        for x in xfit2:
            yfit2=np.append(yfit2,Freundlichfit(x))
        print("The fit coefficient at {0} is: ".format(T2),a2,b2)#,aerr2,berr2)
#################################################################################################
if ifheat == "Y" or ifheat == "y":
    DP=np.array([])
    Qfin=np.array([])

    length=0
    for i in range(GRID):
        for j in range(GRID):
            if abs(yfit1[i]-yfit2[j])<1E-6 and xfit2[j] != 0:
                DP=np.append(DP,xfit1[i]/xfit2[j])
                Qfin=np.append(Qfin,yfit1[i])
                length+=1
                continue
    
    DH=np.zeros([length])
    for k in range(length):
        DH[i]=R*math.log(DP[k])/(1/T2-1/T1)
    
    with open('Output.csv','w',newline='') as csvfile:
        Owriter=csv.writer(csvfile)
        Owriter.writerow('Q','DH')
        for k in range(length):
            Owriter.writerow([Qfin[k],DH[k]])
#################################################################################################
plt.figure(figsize=(10,5),dpi=80)
ax1=plt.subplot(1,2,1)
plt.sca(ax1)
plt.xlabel("Pressure (Pa)")
plt.ylabel("Q (cm^3/g)")
plt.plot(x1,y1,label="{0}K experiment".format(T1))
plt.plot(xfit1,yfit1,label="{0}K fit".format(T1),linestyle="--")
plt.legend(loc="upper left")
if ifheat == "Y" or ifheat == "y":
    ax2=plt.subplot(1,2,2)
    plt.sca(ax1)
    plt.plot(x2,y2,label="{0}K experiment".format(T2))
    plt.plot(xfit2,yfit2,label="{0}K fit".format(T2),linestyle="--")
    plt.sca(ax2)
    #ax2.plt.xlabel()
    #ax2.plt.ylabel()
    plt.plot(DP,Qfin)
plt.savefig("Absorption.png",dpi=300)
plt.show()

在程序中首次尝试的内容

  1. 使用Pandas库中的read_excel()函数读取excel文件,使用方法与numpy.loadtxt()类似,同样拥有usecols,skiprows等参数,其usecols可以直接赋值为字符串,对应excel中的列标字母。注意对于没有header的内容需要加上header=None,否则第一行内容会被认为是列标题。read_excel()返回的是一个元组,要读取多列内容时不能使用x,y=的形式,得分别赋值。

  2. 使用Csv库中的writer()函数将内容输出到csv文件,其使用方法与C++中的ofstream类似,需先定义一个类名称Qwriter=csv.writer(),然后通过该名称的.writerow()函数将内容以行的形式输出。

  3. 使用Matplotlib.pyplot库中的subplot函数进行多子图的图表绘制。使用时首先通过赋值的方式ax1=subplot(1,2,1)确定子图的名称与位置,在绘图时则通过sca(ax1)函数声明在该子图中绘图。

一些小细节

  1. 对于nan数字的判断,numpy库中的isnan()函数可以实现。

  2. 对于字符串的格式化输出,可以使用format()函数实现。具体形式为"{0} is NO.1".format(a)"{a1} is NO.1".format(a1=a)

  3. Python中的函数内变量与全局变量互通,这点与C++不同。

问题与不足

  1. 在读取BET仪器直接生成的xls格式文件时发生了错误,似乎pandas.read_excel()对旧格式的excel文件不是很支持。目前需要另存为xlsx格式再使用。

  2. 在尝试将程序打包为exe执行文件时出现了无法创建***.zip的错误,还未能解决。

  3. 目前手头没有数据,所以没有对计算吸附焓的部分进行验算,不过根据之前C++的结果来看,应该没什么问题。

吸附等温线拟合

其他

在Windows环境下,检查pip各个库的版本使用命令: pip list

更新库使用命令: pip install -U xxx

若出现权限问题,则使用: pip install -U xxx --user

参考资料

用Python作科学计算

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,869评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,716评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,223评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,047评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,089评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,839评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,516评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,410评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,920评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,052评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,179评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,868评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,522评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,070评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,186评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,487评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,162评论 2 356

推荐阅读更多精彩内容