废话少说,先上效果图
可用的技术路线
自动化的需求
- 多通道,多组,数据量比较大
- 常规数据处理,方案一定,几乎都是重复性的操作
- 数据量大,对原数据进行操作,容易污染原数据,也容易出错
- 数据只能用专业软件打开,不利用共享
以上都是废话,最主要的是重复性工作,占用大部分时间,导致效率低下。有时候需求是多个评估指标,或者又临时加指标,所以又不得不把原来的数据重复算一遍,打开超级大的文件,会很凌乱。
为什么其他软件都可以自动化,偏偏LMS Testlab不行?
- LMS testlab其实也提供了COM层的接口,什么是COM层?按我的理解就是程序在window系统上注册了一个对外开放的接口,方便自动化操作。下面这种全损图就是Excel的COM接口,VB代码初始化一个Excel应用如下:
Dim ExcelApp As Excel.Application ExcelApp = CreateObject("Excel.Application")
。
LMS帮助文档Automation.pdf里面有示例和接口说明,比较遗憾的是使用10.A版本,这种长久不更新的技术文档,几乎是暗示你不要使用这个方法了。
- 选择matlab。在命令窗口把文件拖进去,出现
load('example.mat')
,变量栏里面已经出现需要的数据,可以像剥笋一样把数据一层层打开……matlab是一个非常优秀的工程软件。但是它是收费的,而且体积很大,相对来说比较封闭,对于简单的文件操作来说选它不是太适合。对我来说它最致命的缺点就是十分奇怪的数据类型。
最终选择python
不要什么原理,本人的追求就是开箱即用。
技术路线
- 主要程序如下:
# 先导入包
import os
import pandas as pd
from scipy.io import loadmat
import numpy as np
from scipy import signal
from scipy import math
from scipy import integrate
import matplotlib.pyplot as plt
def get_rms(records):
'''求时域信号的有效值,不是均值'''
# return records.apply(lambda x: math.sqrt(sum(x**2) / len(records)))
return math.sqrt(sum([x**2 for x in records]) / len(records))
# 定义几个常用的方法,以后如果多了建议把这一块单独设置为类
def get_max_level(a_rms, a0=10**-6):
'''求加速度振级'''
return 20*math.log(a_rms/a0, 10)
def vibt_level_diff(lvf, lvr):
'''
振级落差,振级落差 = 隔振前加速度振级 - 隔振后加速度振级
落差为正,有隔振效果,落差为负,振动经悬置传递后被放大
'''
deltav = lvf - lvr
pj = ''
if deltav>0:
pj = '悬置有隔振效果'
else:
pj = '振动经悬置传递后被放大'
return deltav, pj
# 下面主要是解析mat文件中包含的数据
m = loadmat('3.mat') #读取mat文件
data1 = pd.DataFrame(m['Signal'][0])
datay = pd.DataFrame(data1['y_values'][0][0])
datay1 = pd.DataFrame(datay['values'][0]) #这里就是所有振动数据的合集了
dataname1 = pd.DataFrame(data1['function_record'][0][0])
dataname2 = pd.DataFrame(dataname1['name'][0]).T
dataname2['测点位置'] = dataname2[0].apply(lambda a: ''.join(list(a))) # 包含测点的信息
dataname2.drop(columns=[0], inplace=True)
datay1.columns = list(dataname2['测点位置'])
testdata = pd.DataFrame(dataname1['creation_time'][0][0]) #获取文件创建时间
dataname2['创建时间'] = testdata[0].apply(lambda a: ''.join(list(a)))
testdata= pd.DataFrame(dataname1.last_modification_time[0][0]) #获取文件最后修改时间信息
dataname2['修改时间'] = testdata[0].apply(lambda a: ''.join(list(a)))
testdata= pd.DataFrame(dataname1.weighting[0][0]) #获取文件最后修改时间信息
dataname2['加权函数'] = testdata[0].apply(lambda a: ''.join(list(a)))
dataname2['数采通道'] = [x[0][0]for x in list(pd.DataFrame(pd.DataFrame(dataname1.primary_channel[0][0])['id'][0][0])[0])]
dataname2['窗函数'] = pd.DataFrame(pd.DataFrame(pd.DataFrame(dataname1.energy_amplitude_transform[0][0])['windows'][0][0])['type'][0][0])[0].apply(lambda a: ''.join(list(a)))
dataname2['项目文件'] = pd.DataFrame(pd.DataFrame(dataname1['TL_export_properties_annotation'][0][0])['project_name'][0][0])[0].apply(lambda a: ''.join(list(a)))
dataname2['section文件'] = pd.DataFrame(pd.DataFrame(dataname1['TL_export_properties_annotation'][0][0])['section_name'][0][0])[0].apply(lambda a: ''.join(list(a)))
dataname2['run目录'] = pd.DataFrame(pd.DataFrame(dataname1['TL_export_properties_annotation'][0][0])['run_name'][0][0])[0].apply(lambda a: ''.join(list(a)))
dataname2['实际开始测时间'] = pd.DataFrame(pd.DataFrame(dataname1['TL_export_properties_annotation'][0][0])['absolute_time'][0][0])[0].apply(lambda a: ''.join(list(a)))
dataname2['通道类型'] = pd.DataFrame(pd.DataFrame(dataname1['TL_export_properties_annotation'][0][0])['channel_group'][0][0])[0].apply(lambda a: ''.join(list(a)))
dataname2['文件路径'] = pd.DataFrame(pd.DataFrame(dataname1['TL_export_properties_annotation'][0][0])['orig_location'][0][0])[0].apply(lambda a: ''.join(list(a)))
datax = pd.DataFrame(data1['x_values'][0][0])
startvalue = datax.start_value[0][0][0] #时域开始点
increment = datax.increment[0][0][0] #步长
datalen = datax.number_of_values[0][0][0] #时间长度,这个值也可以通过 len(datay1)求出
t = len(datay1)*increment+startvalue #信号长度,这个可以用来校核信号是否取完整了
datainfo = pd.DataFrame(datax.quantity[0][0])
info = datainfo['info'][0][0] #这是显示data保存的信息
dataname2['采集开始点'] = startvalue
dataname2['步长'] = increment
dataname2['采样频率'] = 1/increment
dataname2['样本长度'] = datalen
dataname2['官方信息'] = info
# 查看与数据相关的信息,已经聚合到dataname2里了
dataname2.head()
# 求RMS值,振级
l_rms = [] # 求RMS值
l_zj = []
for col in datay1.columns:
rms = get_rms(list(datay1[col]))
l_rms.append(float('%.3f'%(rms)))
l_zj.append(float('%.3f'%(get_max_level(rms))))
# dic = {}
# diczj = {}
# dic[col+'_RMS'] = float('%.3f'%(get_rms(list(datay1[col]))))
# diczj[col+'_ZJ'] = float('%.3f'%(get_max_level(dic[col+'_RMS'])))
# l_rms.append(dic)
# l_zj.append(diczj)
data_result = pd.DataFrame([list(dataname2['测点位置']), l_rms, l_zj])
# 把data_result整理成适合阅读的数据
data_result = data_result.T
data_result.columns = ['测点', 'RMS', '振级']
上面就是处理的程序了,目前来说还是想到一行写一行,可能是没有对象,所以一直没有面向对象的思维。程序中最关键的是利用pandas解析mat文件,其实只要把数据解析到不能解析为止,就可以对数据进行运算了。以上只是对一个run进行运算,加一个for循环,可以把所有的run都计算出来。我觉得对于处理已经是流程化的数据,自动化不光非常高效,而且能保证原数据的纯洁性,还能进行多次利用。唯一遗憾的是目前还不能实现全自动化,各位同仁有什么比较好的数据处理方法,请不吝赐教。