廢話少說,先上效果圖

格式工廠 屏幕錄像20200318_201935.gif
可用的技術(shù)路線

技術(shù)路線圖.png
自動(dòng)化的需求
- 多通道,多組,數(shù)據(jù)量比較大
- 常規(guī)數(shù)據(jù)處理,方案一定,幾乎都是重復(fù)性的操作
- 數(shù)據(jù)量大,對原數(shù)據(jù)進(jìn)行操作,容易污染原數(shù)據(jù),也容易出錯(cuò)
- 數(shù)據(jù)只能用專業(yè)軟件打開,不利用共享
以上都是廢話,最主要的是重復(fù)性工作,占用大部分時(shí)間,導(dǎo)致效率低下。有時(shí)候需求是多個(gè)評估指標(biāo),或者又臨時(shí)加指標(biāo),所以又不得不把原來的數(shù)據(jù)重復(fù)算一遍,打開超級大的文件,會(huì)很凌亂。
為什么其他軟件都可以自動(dòng)化,偏偏LMS Testlab不行?
- LMS testlab其實(shí)也提供了COM層的接口,什么是COM層?按我的理解就是程序在window系統(tǒng)上注冊了一個(gè)對外開放的接口,方便自動(dòng)化操作。下面這種全損圖就是Excel的COM接口,VB代碼初始化一個(gè)Excel應(yīng)用如下:
Dim ExcelApp As Excel.Application ExcelApp = CreateObject("Excel.Application")。
LMS幫助文檔Automation.pdf里面有示例和接口說明,比較遺憾的是使用10.A版本,這種長久不更新的技術(shù)文檔,幾乎是暗示你不要使用這個(gè)方法了。
excelCOM.PNG- 選擇matlab。在命令窗口把文件拖進(jìn)去,出現(xiàn)
load('example.mat'),變量欄里面已經(jīng)出現(xiàn)需要的數(shù)據(jù),可以像剝筍一樣把數(shù)據(jù)一層層打開……matlab是一個(gè)非常優(yōu)秀的工程軟件。但是它是收費(fèi)的,而且體積很大,相對來說比較封閉,對于簡單的文件操作來說選它不是太適合。對我來說它最致命的缺點(diǎn)就是十分奇怪的數(shù)據(jù)類型。
最終選擇python
不要什么原理,本人的追求就是開箱即用。
技術(shù)路線
python主要的包.png
- 主要程序如下:
# 先導(dǎo)入包
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):
'''求時(shí)域信號的有效值,不是均值'''
# return records.apply(lambda x: math.sqrt(sum(x**2) / len(records)))
return math.sqrt(sum([x**2 for x in records]) / len(records))
# 定義幾個(gè)常用的方法,以后如果多了建議把這一塊單獨(dú)設(shè)置為類
def get_max_level(a_rms, a0=10**-6):
'''求加速度振級'''
return 20*math.log(a_rms/a0, 10)
def vibt_level_diff(lvf, lvr):
'''
振級落差,振級落差 = 隔振前加速度振級 - 隔振后加速度振級
落差為正,有隔振效果,落差為負(fù),振動(dòng)經(jīng)懸置傳遞后被放大
'''
deltav = lvf - lvr
pj = ''
if deltav>0:
pj = '懸置有隔振效果'
else:
pj = '振動(dòng)經(jīng)懸置傳遞后被放大'
return deltav, pj
# 下面主要是解析mat文件中包含的數(shù)據(jù)
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]) #這里就是所有振動(dòng)數(shù)據(jù)的合集了
dataname1 = pd.DataFrame(data1['function_record'][0][0])
dataname2 = pd.DataFrame(dataname1['name'][0]).T
dataname2['測點(diǎn)位置'] = dataname2[0].apply(lambda a: ''.join(list(a))) # 包含測點(diǎn)的信息
dataname2.drop(columns=[0], inplace=True)
datay1.columns = list(dataname2['測點(diǎn)位置'])
testdata = pd.DataFrame(dataname1['creation_time'][0][0]) #獲取文件創(chuàng)建時(shí)間
dataname2['創(chuàng)建時(shí)間'] = testdata[0].apply(lambda a: ''.join(list(a)))
testdata= pd.DataFrame(dataname1.last_modification_time[0][0]) #獲取文件最后修改時(shí)間信息
dataname2['修改時(shí)間'] = testdata[0].apply(lambda a: ''.join(list(a)))
testdata= pd.DataFrame(dataname1.weighting[0][0]) #獲取文件最后修改時(shí)間信息
dataname2['加權(quán)函數(shù)'] = testdata[0].apply(lambda a: ''.join(list(a)))
dataname2['數(shù)采通道'] = [x[0][0]for x in list(pd.DataFrame(pd.DataFrame(dataname1.primary_channel[0][0])['id'][0][0])[0])]
dataname2['窗函數(shù)'] = 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['項(xiàng)目文件'] = 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['實(shí)際開始測時(shí)間'] = 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] #時(shí)域開始點(diǎn)
increment = datax.increment[0][0][0] #步長
datalen = datax.number_of_values[0][0][0] #時(shí)間長度,這個(gè)值也可以通過 len(datay1)求出
t = len(datay1)*increment+startvalue #信號長度,這個(gè)可以用來校核信號是否取完整了
datainfo = pd.DataFrame(datax.quantity[0][0])
info = datainfo['info'][0][0] #這是顯示data保存的信息
dataname2['采集開始點(diǎn)'] = startvalue
dataname2['步長'] = increment
dataname2['采樣頻率'] = 1/increment
dataname2['樣本長度'] = datalen
dataname2['官方信息'] = info
# 查看與數(shù)據(jù)相關(guān)的信息,已經(jīng)聚合到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['測點(diǎn)位置']), l_rms, l_zj])
# 把data_result整理成適合閱讀的數(shù)據(jù)
data_result = data_result.T
data_result.columns = ['測點(diǎn)', 'RMS', '振級']
上面就是處理的程序了,目前來說還是想到一行寫一行,可能是沒有對象,所以一直沒有面向?qū)ο蟮乃季S。程序中最關(guān)鍵的是利用pandas解析mat文件,其實(shí)只要把數(shù)據(jù)解析到不能解析為止,就可以對數(shù)據(jù)進(jìn)行運(yùn)算了。以上只是對一個(gè)run進(jìn)行運(yùn)算,加一個(gè)for循環(huán),可以把所有的run都計(jì)算出來。我覺得對于處理已經(jīng)是流程化的數(shù)據(jù),自動(dòng)化不光非常高效,而且能保證原數(shù)據(jù)的純潔性,還能進(jìn)行多次利用。唯一遺憾的是目前還不能實(shí)現(xiàn)全自動(dòng)化,各位同仁有什么比較好的數(shù)據(jù)處理方法,請不吝賜教。
