气质结果重复性比较和pdf结果文件的批处理
顶空固相微萃取结合气相质谱(SPME-GC-MS)试验过程的自动化可能性
背景
最近一直在学院的色谱质谱实验 测定苹果果实的香气。发现测定过程非常复杂,由于仪器灵敏度很高,因此为了保障数据的一致性,需要及时进行报告结果的计算和校对。这意味着实验员的精力同时分散在平衡、吸附、上样、解析、数据导出和结果计算。毫无疑问,这是一个十分困难的任务。但由于每一针样之间时间间隔很长,而且不需要任何的电脑操作为自动化过程留下了空间和可能性。
另外,气质试验数据的导出整理,用常规方法也是一项浩大的工程。师姐的方法是,将GCMS结果文件qgd文件先逐一导出为PDF,再将数据从pdf转移到word表格,在化合物名称部分做一些修正后从word导出到excel。过程并不复杂,但是重复性和机械性很高,而且很耗时间。
假想自动化方案
1、qgd文件转化pdf文件过程
根据经验,在样品登录/等待的过程和上样点击开始(包括2.5min后拔针)后有很长一段电脑的闲置时间,因此可以编写一个自动化的脚本,在这个空隙将前一针已经结束的结果文件转化为pdf文件。
echo "还没写,而且好像肉动也没啥>.<!"
2、数据重复性检查
在一个样品的所有重复都已经测定完毕的情况下,需要检查样品数据的重复性。首先还是将结果文件导出为报告。下面是我的方案,供大家参考:
import pdfplumber as pr
import pandas as pd
import re
from io import StringIO
import numpy as np
import matplotlib.pyplot as plt
import os
import sys#目标文件筛选函数
def data_filter(aromadir):#判断路径是否存在if os.path.exists(aromadir):#列出路径下所有的子目录pdf_reports = os.listdir(aromadir)#筛选出所有文件后缀为pdf并且文件名包含“32_15_p”的文件pdf_reports = [x for x in pdf_reports if x[-4:] == '.pdf' and "32_15_p" in x]#如果筛选结果为空报错if not pdf_reports:raise Exception('the dir has no report file')else:#路径不存在报错raise Exception('sorry, the dir is not exist!') #初始化一个空的pandas数据框result = temp = pd.DataFrame({})#遍历筛选结果并且提取pdf信息for report in pdf_reports:temp = get_pdfinfo(aromadir+report)#合并提取后的数据result = pd.concat([result,temp],axis=1)return result#从pdf提取数据的函数
def get_pdfinfo(pdffile):#在pdf报告文件可靠的情况下,这个异常捕获没必要,但压缩和转移的过程中很有可能导致pdf损坏,为了防止程序退出,加上了这个异常捕获try:with pr.open(pdffile) as pdf:content = ''#遍历所有页面,提取所有页面的文本for i in range(len(pdf.pages)):page = pdf.pages[i]#去除每一页的底部的页码和顶部的页眉page_content = '\n'.join(page.extract_text().split('\n')[2:-1])#每一页的内容拼接到一起content = content+page_content+'\n'except Exception as e:#如果出现pdf损坏,打印错误信息和当前文件名,并且返回一个空文件,程序继续进行print(e)print(pdffile)os.system("rm -rf %s"%pdffile)return pd.DataFrame({})#正则提取物质含量表temp = re.search('(峰表 TIC)(.*?)(谱库)', content, re.S)#正则提取样品名trial_name = re.search('(样品名 :)(.*?)(\n)', content, re.S)temp = temp.group(2)#把content写入字符串缓冲区temp = StringIO(temp)#利用连续的两个空格" "作为分隔符以csv文件格式导入pandas转化为数据框df = pd.read_table(temp, sep=' ', header=None, skiprows=2, skipfooter=1, engine='python')#化合物名称的处理,将控制转化为空字符串df[10] = df[10].fillna('')df[11] = df[11].fillna('')#拼接化合物名称df[10] = df[10]+df[11]#删除临时产生的列(分割问题导致的)df = df.drop(labels=[9,11], axis=1)#加入样品名df[9] = trial_name.group(2)trial_name = trial_name.group(2)#保留1、4、9、10列df = df.loc[:, [1, 4,9, 10]]#重命名列索引df.columns = ['Rtime', 'area', 'sample_name', 'chemical_name']#去除化合物名称两头的不可见字符df['chemical_name'] = df['chemical_name'].apply(func = lambda x:x.strip())#获取内标峰面积,为了防止样品质量差没有内标,加了个异常捕获try:#获取内标面积ns_area = df.loc[df['chemical_name']=='3-Nonanone', ['area']].values[0]except:#无内标则打印出pdf结果文件名并返回空数据框print("无内标:", pdffile)return pd.DataFrame({})#含量计算,峰面积比乘以内标的质量【总感觉这里好像错了(>.<)】df[trial_name] = df['area']/ns_area*0.65928#保留两位小数df[trial_name] = df[trial_name].round(2)#争议过程,由于在报告中会出现不同保留时间化学物质名称相同的情况,本方案的处理逻辑没办法消除这种影响,所以一竿子打死,对于重复值只保留第一次出现的项if any(df.duplicated(subset="chemical_name")):df.drop_duplicates(subset="chemical_name", inplace=True, keep="first")#将去重后的化合物名称作为(行)索引(行索引必须唯一)df.set_index("chemical_name", inplace=True)#只保留化合物含量这一列数据df = df[trial_name]return df#雷达图绘制函数
def draw_radar(result):#数据归一化,把数据缩放到0-1result = data_standard(result, 1)# 雷达图标签labels = result.index# 标签数量num_vars = len(labels)# 将圆等分并且保存对应的角度angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist()# 使圆首尾相接angles += angles[:1]#matplotlib制订画布大小,并指定极坐标图方法# ax = plt.subplot(polar=True)fig, ax = plt.subplots(figsize=(15,15), subplot_kw=dict(polar=True))# 绘制雷达图的辅助函数def add_to_radar(sameple):values = result[sample].tolist()values += values[:1]#绘制和填充ax.plot(angles, values, linewidth=1, label=sample)ax.fill(angles, values, alpha=0.25)# 遍历所有的列for sample in result.columns:add_to_radar(sample)#add_to_radar('peugeot 504 1979', '#429bf4')#add_to_radar('ford granada 1977', '#d42cea')# 设置顺时针排列并且从12点钟方向开始ax.set_theta_offset(np.pi / 2)ax.set_theta_direction(-1)# 在对应角度摆放标签ax.set_thetagrids(np.degrees(angles[:-1]), labels)# 通过标签位置调整对应姿态for label, angle in zip(ax.get_xticklabels(), angles):if angle in (0, np.pi):label.set_horizontalalignment('center')elif 0 < angle < np.pi:label.set_horizontalalignment('left')else:label.set_horizontalalignment('right')# 设定y轴的#ax.set_ylim(0, 100)# 设定网格线# ax.set_rgrids([20, 40, 60, 80, 100])#标签位置ax.set_rlabel_position(180 / num_vars)# 设定刻度颜色ax.tick_params(colors='#222222')# 标签大小.ax.tick_params(axis='y', labelsize=8)# 网格线颜色ax.grid(color='#AAAAAA')#设置最外围网格的颜色.ax.spines['polar'].set_color('#222222')# 设置背景色.ax.set_facecolor('#FAFAFA')# 标题.ax.set_title('apple aroma radar chart', y=1.08)# 添加图例.#ax.legend(loc='upper right', bbox_to_anchor=(1.3, 1.1))#图例位置ax.legend(loc='best')#图片紧凑排布plt.tight_layout()#电脑plt.show()就OK,电脑坏了这是自创的termux的plt.show()方法fig.savefig("radar.png")os.system("termux-open radar.png")#数据标准化函数
def data_standard(result, axis=0):#苹果特征香气want = [".alpha.-Farnesene", "1-Butanol, 2-methyl-", "1-Hexanol", "2-Hexenal, (E)-","Hexanal", "Acetic acid, butyl ester","Acetic acid, hexyl ester"]#特征筛选result = result.loc[want, :]#判断数据排布的轴向if axis:for raw in result.index:#标准化方法用数据除以最大值result.loc[raw] = result.loc[raw]/(result.loc[raw].max())else:for col in result.columns:result[col] = (result[col])/(result[col].max())return resultif __name__=="__main__":#pdf结果文件的存放路径aromadir="../../bluetooth/aroma_report/"#文件过滤result=data_filter(aromadir)#空值处理,空值替代为0result.fillna(value=0, inplace=True)#导出为csv/excel文件#result.to_csv("aroma.csv", sep=",")#绘制雷达图draw_radar(result)
上图就是试验过程中三个生物学重复的香气物质雷达图,可见SPME-GC-MS方法的重复性还是比较差的,虽然这可能与样品不均质也有一定关系。
3、pdf结果文件数据的提取和整理
因为这个过程在绘制雷达图的过程中用到过,并且有对应的函数因此只放main后的部分,如下:
if __name__=="__main__":#pdf结果文件的存放路径aromadir="../../bluetooth/aroma_report/"#文件过滤result=data_filter(aromadir)#空值处理,空值替代为0result.fillna(value=0, inplace=True)#导出为csv/excel文件result.to_csv("aroma.csv", sep=",")
展示结果:
程序会运行的很慢,像卡住了一样。由于电脑坏了,我用平板跑的。荣耀V6,处理60个pdf文件导出结果大概花了15min,毕竟平板算力有限,用电脑应该会快很多。如果在程序中加入一个比如说ASCII动图之类的动态反馈使用感会好一点,但是我不想写(反正又没人用, 而且再写毕不了业了)。
从这里可以看到,背景中提到的问题都已经基本解决。但是实验室的电脑是一台古老的windows xp,可以运行的python版本非常低,而且很多库对于python并不支持。因此可以通过python自带的打包工具Pyinstaller打包成exe。如果是高版本windows之间的转递也可以用embeddable打包。
写在最后
其实最后是一个技术乞讨>.<。最近笔记本的屏幕坏了,被迫成为了一台远程电脑。但是我使用的内网穿透工具不怎么稳定,想问问大家有没有稳定并且提供http流量穿透(想搭个小网站)的内网穿透工具,最好是免费的(贫穷的成年人不想为没有金钱回报的玩物做任何投资)。
气质结果重复性比较和pdf结果文件的批处理相关推荐
- ABBYY15免费版直接编辑PDF格式文件
日常生活中,我们常常使用PDF格式的文件.其优点就是PDF的文本内容不会随着软件版本.电脑字体的变化而变化,保证了其完整性.但也正因为这一点,如果没有源文件,我们就很难对PDF文档的内容进行编辑了.今 ...
- html 实现动态在线预览word、excel、pdf等文件
word+excle+pdf表格在线浏览 通过iframe直接引用微软提供的方法 <iframe src='https://view.officeapps.live.com/op/view.as ...
- 纯前端下载pdf链接文件,而不是打开预览的解决方案
纯前端下载pdf链接文件,而不是打开预览的解决方案 参考文章: (1)纯前端下载pdf链接文件,而不是打开预览的解决方案 (2)https://www.cnblogs.com/jackson-yqj/ ...
- 后缀为PDF的文件要用什么工具才能打开?
今天在迅雷里下了些资料,解压后,文件的后缀为PDF我的系统只装了office 2003,不支持这个PDF,后来我又装了中文版的WPS Office 2005企业版,结果还是打不开. 以前也见过后缀为P ...
- 使用PHP读取和创建txt,doc,xls,pdf类型文件
使用PHP读取和创建txt,doc,xls,pdf类型文件 PHP读取或者创建txt,doc,xls,pdf各个类型文件的方法. php读取(文本.txt)文件: 一般是使用fopen.fgets的方 ...
- PHP读取创建txt,doc,xls,pdf类型文件
2019独角兽企业重金招聘Python工程师标准>>> PHP读取或者创建txt,doc,xls,pdf各个类型文件的方法. php读取(文本.txt)文件: 一般是使用fopen. ...
- java jsp导出pdf文件_JSP页面导出PDF格式文件
JSP页面导出PDF格式文件基本在前端页面可以全部完成 添加下载链接的点击事件 var downPdf = document.getElementById("downLoad"); ...
- php读取doc pdf文件,PHP读取创建txt,doc,xls,pdf类型文件
PHP读取或者创建txt,doc,xls,pdf各个类型文件的方法. php读取(文本.txt)文件: 一般是使用fopen.fgets的方法,例如: $fp=fopen('文件名.txt','r') ...
- itextpdf实现PDF模板文件动态赋值和绘制条形码
步骤一 创建工程,导入maven依赖如下: <dependency><groupId>com.itextpdf</groupId><artifactId> ...
最新文章
- 数通手稿留档——ISIS
- c#中常用集合类和集合接口之集合类系列
- LeetCode 1376. 通知所有员工所需的时间(DFS)
- 大学语言c 离线作业,大学语文C离线作业(2013下).doc
- 黑屏后面藏了什么?--解读微软打击盗版
- 计算机图形学课程设计内容及要求
- Python3 requests 12306查票模块
- 一个Windows进程管理的小工具源码
- 微信小程序开发笔记--07
- 百度网盘网页版增加倍速播放速度
- C语言switch语句用法详解
- 数据库PostrageSQL-证书认证
- 文本框”输入关键字 “提示
- bzoj 4408: [FJOI2016]神秘数 主席树
- MySql CHECK使用方法
- 思博伦OpenFlow性能测试白皮书(上)
- webIx之表单提交
- android类加载器ClassLoader
- 照片游技术会取代街景车吗?
- 灾备系统 RTO与RPO
热门文章
- 使用gcc以及makefile编译C程序
- context概念理解
- 域名防封-微信防屏蔽的原理以及实现
- 这34道接口测试 Jmeter面试题,你会吗?
- 中关村示范区两项人才特区政策落地
- Android毕业设计——基于Android+Tomcat的网络视频探索系统设计与实现(毕业论文+程序源码)——网络视频探索系统
- I3D模型_2017_CVPR
- SecureCRT使用sftp传输文件到服务器
- “Apple Glass”设备(苹果眼镜)的功能介绍
- Linux 创建文件系统及挂载文件系统流程详解(转)