一、可用的技術(shù)路線

技術(shù)路線圖.png
- 通過com層操作。建議學(xué)習(xí)LMS幫助文檔Automation.pdf,里面有示例和接口說明。~~
- 通過導(dǎo)出.mat文件,使用matlab進(jìn)行操作。
- 通過導(dǎo)出.mat文件,使用python進(jìn)行操作,本文使用的方法。
根據(jù)個(gè)人喜歡,選擇對應(yīng)方法。
使用LMS處理數(shù)據(jù),每個(gè)人都有自己比較順手的方法。因?yàn)槲覀€(gè)人比較討厭重復(fù)性工作以及抄數(shù)據(jù),所以一直都在追求自動(dòng)化的方法,哪怕只有點(diǎn)點(diǎn)都行。
自動(dòng)化能夠解放我的工作,同時(shí)能夠減少出錯(cuò)率,廢話不多說,直接上代碼。
代碼塊
1. 導(dǎo)入包
import os #系統(tǒng)操作包,我主要用來操作文件夾與文件
import pandas as pd # 非常熱門的數(shù)據(jù)處理工具
from scipy.io import loadmat #科學(xué)計(jì)算處理包,對標(biāo)matlab
from scipy import signal #信號處理包,主要用了濾波功能
from scipy.fftpack import fft, fftfreq, fftshift #快速傅里葉變換
from scipy import math #數(shù)學(xué)計(jì)算包
import matplotlib.pyplot as plt # 畫圖包
import win32com.client #win32com包,這里用不到,因?yàn)槲铱床欢?import numpy as np # 矩陣計(jì)算工具,非常厲害
import pymongo #mongo數(shù)據(jù)庫包
2. 定義常用的方法
#求時(shí)域信號的有效值,不是均值
def get_rms(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 = '振動(dòng)經(jīng)懸置傳遞后被放大'
return deltav, pj
# 濾波
# wn = 2*1024/12800 # 采樣率12800, 截止頻率1024,
def mylowpass(data,wn = 2*1024/12800):
b, a = signal.butter(10, wn, 'lowpass')
filtedData = signal.filtfilt(b, a, data)
return filtedData
# 傅里葉變換
def myfft(mydata, t, n):
l_max_hz = []
l_max_a = []
n = fourier.size
freq = fftfreq(n, t)
freq = fftshift(freq)[int(freq.size/2.0): freq.size]
fourier = fftshift(fourier)[int(fourier.size/2.0): fourier.size]
fourier = 2/n*np.abs(fourier)
max_three_index = fourier.argsort()[::-1][0:1] #最大的前三位數(shù)
big1 = [[fourier[i], freq[i]] for i in max_three_index]
l_max_a.append(big1[0][0])
l_max_hz.append(big1[0][1])
return l_max_a, l_max_hz
上述方法可以根據(jù)自己的需求添加。建議將方法設(shè)置在方法類中,需要什么就取什么。
3. 載入文件
os.chdir(r'E:\2020test\truck01_data\truck01_hulan') #切換到數(shù)據(jù)目錄
print(f'已經(jīng)切換到路徑:{os.getcwd()}')
print('*'*50)
matdirs = [matdir for matdir in os.listdir() if matdir.endswith('.mat')] #讀取目錄下后綴是.mat的所有文件
print(f'當(dāng)前路徑下的文件有:{[x for x in os.listdir()]}')
4. 計(jì)算并輸出數(shù)據(jù)
for matdir in matdirs:
filename = matdir #需要把這個(gè)文件名也存到數(shù)據(jù)庫重
print(f'開始處理{matdir}')
m = loadmat(filename) #讀取mat文件
if 'Signal' in m.keys():
data1 = pd.DataFrame(m['Signal'][0])
else:
data1 = pd.DataFrame(m['Signal_0'][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
### 經(jīng)緯度信息
latlong = pd.DataFrame(m['Signal_1'][0][0][1][0][0][0], columns = ['維度', '精度']) # 經(jīng)緯度信息
factor = pd.DataFrame(m['Signal_1'][0][0][1][0][0][1][0][0][1][0])['factor'][0][0][0] #因子
log_reference = pd.DataFrame(m['Signal_1'][0][0][1][0][0][1][0][0][1][0])['log_reference'][0][0][0] #我也不知道是啥
offset = pd.DataFrame(m['Signal_1'][0][0][1][0][0][1][0][0][1][0])['offset'][0][0][0]
unit = m['Signal_1'][0][0][1][0][0][1][0][0][0][0] #經(jīng)緯度單位
speed = pd.DataFrame(m['Signal_4'][0][0][1][0][0][0]*3.6, columns=['車速']) # gps車速,單位m/s
altitude = pd.DataFrame(m['Signal_2'][0][0][1][0][0][0], columns = ['altitude'])# Altitulde 海拔信息
data_lat_log_velocity = pd.concat([latlong, speed, altitude], axis=1)
# m['Signal_3'] # 東速度 西速度 啥的 不用管它,不讀
# m['Signal_5'] #衛(wèi)星數(shù)
# m['Signal_6'] #can轉(zhuǎn)速,導(dǎo)不出來
# 進(jìn)行低通濾波
datay1_lp = datay1.apply(mylowpass, axis=0)
# 計(jì)算常規(guī)評價(jià)指標(biāo)如RMS等
l_rms = [] # 求RMS值
l_zj = [] # 求振級
l_max = [] #求最大值
l_mean = [] # 求均值
l_std = [] # 求均方差
l_min = [] # 求最小值
l_true_max = [] #求絕對值最大值
for col in datay1_lp.columns:
data_describle = datay1_lp[col].describe()
rms = get_rms(datay1_lp[col])
l_rms.append(float('%.3f'%(rms)))
l_zj.append(float('%.3f'%(get_max_level(rms))))
l_max.append('%.3f'%data_describle['max'])
l_mean.append('%.3f'%data_describle['mean'])
l_std.append('%.3f'%data_describle['std'])
l_min.append('%.3f'%data_describle['min'])
l_true_max.append('%.3f'%abs(datay1_lp[col]).max())
data_result = pd.DataFrame([list(dataname2['測點(diǎn)位置']), l_rms, l_zj, l_max, l_mean, l_std, l_min, l_true_max])
data_result = data_result.T
data_result.columns = ['測點(diǎn)', 'RMS', '振級','正向最大值','平均值','方差','最小值','絕對值最大值']
#計(jì)算RMS綜合值
data_result_v1 = data_result.copy()
data_result_v1['RMS_綜合'] = 0
data_result_v1['振級_綜合'] = 0
for row in range(int(len(data_result) / 3)):
data_result_v1.loc[3*row+2,['RMS_綜合']] = '%.3f'%(np.sqrt(data_result.loc[3*row,'RMS']**2+data_result.loc[3*row+1,'RMS']**2+data_result.loc[3*row+2,'RMS']**2))
data_result_v1.loc[3*row+2,['振級_綜合']] = '%.3f'%(np.sqrt(data_result.loc[3*row,'振級']**2+data_result.loc[3*row+1,'振級']**2+data_result.loc[3*row+2,'振級']**2))
# 做傅里葉變換
# def myfft()
datay1.apply(myfft, args=(dataname2.loc[0,'步長'], len(datay1),),axis=0)
data_result_v1['平均車速'] = speed.mean()
dataiii = pd.DataFrame(datay1.apply(myfft, args=(dataname2.loc[0,'步長'], len(datay1),),axis=0))
data_result_v1['最大加速度_a'] = list(pd.DataFrame(dataiii)[0].apply(lambda a:a[0][0]))
data_result_v1['最大加速度_Hz'] = list(pd.DataFrame(dataiii)[0].apply(lambda a:a[1][0]))
#保存文件
data_result_v1.to_excel(dataname2['section文件'][1]+'_'+dataname2['run目錄'][1]+'.xlsx',index=False, dtype='float64')
print(f'{matdir}已經(jīng)處理完畢')
print('Successed!!')
- 振動(dòng)時(shí)域信號放在
datay1中
datay1.PNG - 信號相關(guān)信息存放在
dataname2中
dataname2.PNG - 輸出結(jié)果放在
data_result_v1中
data_result.PNG
根據(jù)業(yè)務(wù)需求制定相關(guān)方法,代入腳本計(jì)算出相關(guān)結(jié)果。
我個(gè)人認(rèn)為上面的自動(dòng)化腳本好處還是有的。 - 輸出的三張表分別存儲(chǔ)了時(shí)域數(shù)據(jù),數(shù)據(jù)信息,輸出結(jié)果。其中數(shù)據(jù)信息和輸出結(jié)果的索引都是通道,所以他們可以直接關(guān)聯(lián)的。
時(shí)域數(shù)據(jù)列標(biāo)簽就是其他兩張表的行標(biāo)簽,也可以關(guān)聯(lián)。針對上述的數(shù)據(jù),我大概做了兩個(gè)數(shù)據(jù)庫的存儲(chǔ)模型,非常簡陋。 - 數(shù)據(jù)庫模型一
{
"_id" : ObjectId("5e73f335d913cc99e304489d"),
"測點(diǎn)" : "the test point",
"RMS" : "2.323",
"振級" : "127.321",
"正向最大值" : "11.193",
"平均值" : "-0.006",
"方差" : "2.323",
"最小值" : "-12.654",
"絕對值最大值" : "12.654",
"測點(diǎn)位置" : "the test point",
"創(chuàng)建時(shí)間" : "2020/03/07 17:37:57",
"修改時(shí)間" : "2020/03/07 17:37:57",
"加權(quán)函數(shù)" : "NONE",
"數(shù)采通道" : "3",
"窗函數(shù)" : "UNKNOWN",
"項(xiàng)目文件" : "Project1",
"section文件" : "the section name",
"run目錄" : "平直路40km_h 1",
"實(shí)際開始測時(shí)間" : "2020-03-07 09:37:52 ms 726.999",
"通道類型" : "Vibration",
"文件路徑" : "filepath" #
"采集開始點(diǎn)" : "1.2251250597895408e-05",
"步長" : "7.8125e-05",
"采樣頻率" : "12800.0",
"樣本長度" : "301940",
"官方信息" : "Data saved by Testlab in MKS",
"mat文件地址" : "J:\\testlabfile", #對應(yīng)輸出的mat文件
"mat文件" : "3.mat"
}
- 數(shù)據(jù)庫模型二
"result" : [
{
resultinfo,
},... ]
...
"info": {...}
存放在數(shù)據(jù)庫中的好處有很多,比如方便crud(增刪查改),數(shù)據(jù)共享……等等。
5. 后續(xù)計(jì)劃
-
共享數(shù)據(jù)
后續(xù)主要是打算通過api的方式共享數(shù)據(jù),可能選擇flask,fastapi,echarts這些比較簡單親民的框架。 -
數(shù)據(jù)挖掘
通過使用sklearn,XGBOOST,pytorch,paddlepaddle做一些數(shù)據(jù)分析。
??????????,求不要嘲笑。
附圖:python處理的數(shù)據(jù)路線

python主要的包.png