2020-03-24

一、可用的技術(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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容