在从电脑抄写了很多的高效液相数据后,我终于乏了。开始寻思直接获取系统里的数据。

最开始,我尝试直接破解数据文件。很遗憾,以我的计算机水平,这是个只有阿汤哥才能完成的不可能任务。

后来,我打起了剪切板的主意。将液相程序里的数据先暂存到剪切板中,然后从剪切板取出来再做集中处理。下面就我的解决方案作一个简要解说。

Empower3 高效液相报告

Waters的高效液相结果可能长成上面这幅样子,如果将其数据复制出来粘贴到办公表格上,可能会是下面的样子:

高效液相数据复制到办公表格

而实际上我需要的数据可能要长成下面的样子才方便我做进一步的处理:

预处理后的数据

那么问题来了,该如何对复制出来的办公表格数据进行预处理呢?
首先是过滤掉不需要的数据,手动删除或只用所需列,这里留下名称列和面积列就好,总之是很简单的事情。

其次分组的问题。包括两个方面:
第一是将每一个进样数据分开。因为观察到每个进样都有相同的数据起始标记,诸如“名称 保留时间 面积”这样的表头,我遍历了这些标记并取得索引,两个索引之间的即为一个进样数据。
第二是将每个批次分开。在我那个时候,有关物质则已经要做2个平行样品,而含量则需要做4个平行样品。我的升维打击很简单粗暴,将第一步得到的数组按2个或4个分割为一组。

然后是每个进样数据的处理。因为处理方法中会预设组分的名称,也会出现没有名字的组分——即有关物质或杂质。所以可以将组分分成两个小组,有名的和无名的。之所以如此是因为我们可能需要对无名组分进行统计分析,算出最大的单杂和所有总杂,用max()和sum()对数组进行运算就可以得到。
实际上Empower3报告方法中有面积比例,也有未知峰最大和总和的运算,但这是自身做对照的情况下才适用。而如果是用自身的稀释液作参比则不行。浓度和面积虽成线性关系,但却并不意味着浓度稀释多少倍面积也会相应缩小。

最后就是打印了,制表符搭配换行符,复制粘帖出来就是所需要的预处理后数据了。当然也可以直接生成文件。具体详情参见代码。

当时的我只写了数据集中处理的脚本,而将数据暂存到剪切板中有一个要命的关键,要精确控制数据的先后顺序,否则可能导致错乱。我写不出那么智能的脚本,所以只能自己当人肉复制机。但好在复制速度快且根本不用比对,还是省去了不少麻烦。现在的话,我想到了更优的方案。无论Agilent还是Waters都有自动打印图谱的功能,只要将打印机换成虚拟打印机,自动打印出文件,然后用脚本分析这些文件并提取出所需要的数据,就可以解决人肉复制机的问题。虚拟打印其实是个很有用的工具。尤其是面对没有数据接口的封闭程序时,用纸张打印出来太过浪费且效率低下,但如果能打印到文件中去,事情就更轻松的方式。一个人性的程序,应该提供数据批量利用的方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
######
# hplc.py HPLC Data Program 高效液相数据处理
# by cqh.ch 2016-10-24
######

# coding=utf-8
import time
import xlrd
import zipfile

def getSheet(fileName='Book1.xls', sheetName='Sheet1'):#从指定名字的工作簿获得指定名字工作表
xls=xlrd.open_workbook(fileName)
sheet = xls.sheet_by_name(sheetName)
return sheet

def nac(sheet):#nameAreaCleaner 工作表组分与面积数据清洗 传入工作表,依据数据起始标记,将一组原始数据分成两个元素数组,元素一为知名组分面积的数组,元素二为未名组分面积的数组
idx = []#数据起始标记索引
for row in range (0, sheet.nrows):
if sheet.row_values(row) == sheet.row_values(0):#起始标记sheet.row_values(0)
idx.append(row)
arrs = []#存放清洗后的数据组
for k in range(0, len(idx)-1):
know = []#知名组分面积
unknow = []#未名组分面积
bgn = idx[k]+1#数据开始行
end = idx[k+1]#数据结束行
for row in range(bgn, end):
if(sheet.cell(row, 1).value != ''):#名称不为空
know.append(sheet.cell(row, 3).value)
elif(sheet.cell(row, 1).value == '' and sheet.cell(row, 3).value != ''):#名称为空但面积不为空
unknow.append(sheet.cell(row, 3).value)
#else:#空行
#print '\n'
arrs.append([know, unknow])
return arrs

def lst(arr, n):#listSplit 数组分割,传入一个数组,将其分割成n个一组
lenIn = len(arr)#源数组长度
if lenIn % n:
lenOut = lenIn / n + 1#目标长度
else:
lenOut = lenIn / n
narr = []#存放目标数组
for m in range(lenOut):
narr.append(arr[m*n : (m+1)*n])
return narr

def adr(arr):#数组去重 array delete repeat
anr = []#存放去重后数组 array not repeat
for x in arr:
if x not in anr:
anr.append(x)
return anr

def ptr(arr, node=0):#数组打印 array printer
m = len(arr)
for i in range (m):
if type(arr[i]) == list:
n = len(arr[i])
temp = '\t' * node
for j in range (n):
temp += str(arr[i][j]) + '\t'
print temp
if node:#默认不打印深层节点
ptr(arr[i], node+1)
else:
print(arr[i])

def hl(arr):#含量 content
for i in range(len(arr)):
temp = ''
for j in range(len(arr[i][0])):
temp += str(arr[i][0][j]) + '\t'
print temp

def yg(arr):#有关物质 related substances
for i in range(len(arr)):
temp = ''
if arr[i][1]:#其他杂质不为空
temp += str(max(arr[i][1])) + '\t' + str(sum(arr[i][1])) + '\t' #其他单个杂质最大 其他杂质总和
else:
temp += '\t\t'
for j in range(len(arr[i][0])):
temp += str(arr[i][0][j]) + '\t'
print temp

def rst(sheet, keyRow=5):#result 将处理好的结果表格转换成字典键值对
arr = []
key = sheet.row_values(keyRow)
for row in range (keyRow+1, sheet.nrows):
val = sheet.row_values(row)
dic = dict(zip(key, val))
arr.append(dic)
return arr

sheet = getSheet(fileName='Book1.xls', sheetName='Sheet1')

#打印一列去重数据
ptr(adr(sheet.col_values(3)))

#将一维数组转换为四维并打印
ptr(lst(adr(sheet.col_values(3)), 4))

# 含量
hl(nac(sheet))

# 有关物质
yg(nac(sheet))