from ctypes import Structure from re import M import pandas as pd import numpy as np import datetime import time, datetime import matplotlib.pyplot as plt from pylab import* from scipy.signal import savgol_filter import os import log path = r'D:\Work\Code_write\data_analyze_platform\USER\lzx\01算法开发\02析锂检测\01下载数据\格林美-Catl7255\原始数据' def get_file(): #创建一个空列表 files =os.listdir(path) files.sort() #排序 file_list= [] for file in files: if not os.path.isdir(path +file): #判断该文件是否是一个文件夹 f_name = str(file) # print(f_name) tr = '\\' #多增加一个斜杠 filename = path + tr + f_name file_list.append(filename) return file_list mylog=log.Mylog('log_diag.txt','error') mylog.logcfg() file_list = get_file() for file in file_list: data = pd.read_csv(file,encoding='GB18030') #----------------------------------------定义滤波函数----------------------------------------------------------------------- def moving_average(interval, windowsize): window = np.ones(int(windowsize)) / float(windowsize) re = np.convolve(interval, window, 'same') return re #----------------------------------------区分充放电数据---------------------------------------------------------------------- df_soc = data['SOC[%]'] df_soc_len = len(df_soc) df_soc_add = df_soc.iloc[df_soc_len-3:df_soc_len-1]#由于对SOC二次微分,需要增加两行数据 df_soc_new = df_soc.append(df_soc_add) df_soc_new_dif = np.diff(df_soc_new,axis=0)#电压一次微分,判断升降 df_soc_new_dif = pd.DataFrame(df_soc_new_dif) df_soc_new_dif[df_soc_new_dif >= 0] = 1#SOC升高或静置 df_soc_new_dif[df_soc_new_dif < 0] = -1#SOC下降 df_soc_new_difdif = np.diff(df_soc_new_dif,axis=0)#三次微分,利用-2,2判断充电-静置与放电-静置的区别 df_soc_new_difdif = pd.DataFrame(df_soc_new_difdif) peak_pos = np.where(df_soc_new_difdif == -2) bot_pos = np.where(df_soc_new_difdif == 2) chrgr_rest_data_temp = data.loc[((data['充电状态'] == 0) & (data['SOC[%]'] > 98) & (data['总电流[A]'] == 0))| ((data['充电状态'] == 2) & (data['SOC[%]'] > 98) & (data['总电流[A]'] == 0))]#接近慢充后静置数据 chrgr_rest_data = chrgr_rest_data_temp.reset_index(drop=True) temp_rest_time = chrgr_rest_data['时间戳'].reset_index(drop=True) rest_time = pd.to_datetime(temp_rest_time) # rest_chrg_time = datetime(rest_time) # delta_time = np.diff(rest_chrg_time) delta_time = (np.diff(rest_time)/pd.Timedelta(1, 'min'))#计算时间差的分钟数 pos = np.where(delta_time > 30) pos_ful_tem = np.insert(pos, 0, 0) pos_len = len(pos_ful_tem) data_len = len(rest_time) pos_ful = np.insert(pos_ful_tem, pos_len, data_len-1) splice_num = [] if len(pos[0]) >= 1: pos_ful_tem = np.insert(pos, 0, 0) pos_len = len(pos_ful_tem) data_len = len(rest_time) pos_ful = np.insert(pos_ful_tem, pos_len, data_len-1) for item in range(0,len(pos_ful)-1): splice_num.extend(item*np.ones(pos_ful[item +1]-pos_ful[item])) splice_num = np.insert(splice_num, 0, 0) else: splice_num = np.zeros(len(temp_rest_time)) pos_ful = np.array([0]) chrgr_rest_data['chrgr_rest'] = splice_num #---------------------------判断数据点数大于30的数据段,对电压微分并画图-------------------------------------------- cellvolt_name=['单体电压'+str(x) for x in range(1,21)] cellvolt_list = cellvolt_name chrgr_rest_check_data = chrgr_rest_data.drop(['GSM信号','故障等级','故障代码','单体压差','绝缘电阻','总电流[A]','总电压[V]','充电状态','单体压差','SOC[%]'],axis=1,inplace=False) chrgr_rest_check_data.fillna(value=0) df_rest_volt_diffdt = pd.DataFrame() df_rest_volt_smooth = pd.DataFrame() df_ini_volt_total = pd.DataFrame() k = 0 for j in range(0,len(pos_ful)-1):#len(pos_ful)-1#有几段充电后静置数据 df_test_rest_data = chrgr_rest_check_data.loc[chrgr_rest_check_data['chrgr_rest'] == j] df_rest_volt_smooth = pd.DataFrame() df_ini_volt = pd.DataFrame() df_test_rest_time = pd.to_datetime(df_test_rest_data['时间戳'],format='%Y-%m-%d %H:%M:%S') df_test_rest_time = df_test_rest_time.reset_index(drop=True) df_data_length = len(df_test_rest_time) if (df_data_length > 30) & ((df_test_rest_time[df_data_length - 1] - df_test_rest_time[0])/pd.Timedelta(1, 'min') > 40):#静置时间大于40min df_test_rest_time_dif_temp = np.diff(df_test_rest_time)/pd.Timedelta(1, 'min') num_list = [] data_jump_pos = np.where(df_test_rest_time_dif_temp > 3) if len(data_jump_pos[0]) > 0: if data_jump_pos[0][0] > 100: for i in range(0,data_jump_pos[0][0],15):##采样密集时每隔10行取数据 num_list.append(i) df_rest_data_temp = df_test_rest_data.iloc[num_list] df_test_rest_data_choose = pd.DataFrame(df_rest_data_temp) df_test_rest_data_choose_else = df_test_rest_data.iloc[data_jump_pos[0][0]+1:len(df_test_rest_data)-1] df_rest_data_recon_temp = df_test_rest_data_choose.append(df_test_rest_data_choose_else) df_rest_data_recon =df_rest_data_recon_temp.reset_index(drop=True) else: df_rest_data_recon = df_test_rest_data else: df_rest_data_recon = df_test_rest_data df_rest_time = pd.to_datetime(df_rest_data_recon['时间戳'],format='%Y-%m-%d %H:%M:%S') df_rest_time = df_rest_time.reset_index(drop=True) df_rest_time_dif_temp = np.diff(df_rest_time)/pd.Timedelta(1, 'min') df_rest_volt = df_rest_data_recon[cellvolt_list] for item in cellvolt_list: window_temp = int(len(df_rest_volt[item])/3) if window_temp%2:#滤波函数的窗口长度需为奇数 window = window_temp else: window = window_temp - 1 step = min(int(window/3),5) df_volt_smooth = savgol_filter(df_rest_volt[item],window,step) df_rest_volt_smooth[item] = df_volt_smooth df_ini_volt = df_ini_volt.append(df_rest_volt_smooth) df_ini_volt.columns = cellvolt_list df_test_rest_volt_diff_temp = np.diff(df_rest_volt_smooth,axis=0) df_test_rest_time_dif = pd.DataFrame(df_rest_time_dif_temp) df_test_rest_volt_diff = pd.DataFrame(df_test_rest_volt_diff_temp) df_test_rest_volt_diffdt_temp = np.divide(df_test_rest_volt_diff,df_test_rest_time_dif)#电压对时间的微分 df_test_rest_volt_diffdt = pd.DataFrame(df_test_rest_volt_diffdt_temp) df_test_rest_volt_diffdt = df_test_rest_volt_diffdt.append(df_test_rest_volt_diffdt.iloc[len(df_test_rest_volt_diffdt)-1]) df_test_rest_volt_diffdt.columns = cellvolt_list if len(df_test_rest_volt_diffdt) > 25: for item in cellvolt_list: df_volt_diffdt_smooth = savgol_filter(df_test_rest_volt_diffdt[item],13,3) df_test_rest_volt_diffdt[item] = df_volt_diffdt_smooth df_test_rest_volt_diffdt['chrgr_rest'] = k df_test_rest_volt_diffdt['时间戳'] = list(df_rest_time) df_ini_volt['chrgr_rest'] = k df_ini_volt['时间戳'] = list(df_rest_time) k = k+1 df_rest_volt_diffdt = df_rest_volt_diffdt.append(df_test_rest_volt_diffdt)#电压对时间的一次微分 df_rest_volt_diffdt.reset_index() df_ini_volt_total = df_ini_volt_total.append(df_ini_volt) df_ini_volt_total.reset_index() #--------------------------------------------------------确认是否析锂---------------------------------------------------------------------------- # df_lipltd_data = pd.DataFrame(columns=['sn','date','liplated']) m_num = 0 df_fig_dvdtdata = pd.DataFrame() df_fig_voltdata = pd.DataFrame() for item in range(0,k): lipltd_confirm = [] lipltd_amount = [] df_check_liplated_temp = df_rest_volt_diffdt.loc[df_rest_volt_diffdt['chrgr_rest'] == item].reset_index(drop = True) df_check_volt_temp = df_ini_volt_total.loc[df_ini_volt_total['chrgr_rest'] == item].reset_index(drop = True) df_lipltd_volt_temp = df_check_liplated_temp[cellvolt_list] df_lipltd_volt_len = len(df_lipltd_volt_temp) df_data_temp_add = df_lipltd_volt_temp.iloc[df_lipltd_volt_len-3:df_lipltd_volt_len-1]#电压对时间的一次微分 df_lipltd_volt_temp_add = df_lipltd_volt_temp.append(df_data_temp_add) # df_lipltd_volt_temp_dif = np.diff(df_lipltd_volt_temp_add,axis=0)#电压一次微分,计算dv/dt # df_lipltd_volt_temp_dif = pd.DataFrame(df_lipltd_volt_temp_dif) # df_lipltd_volt_temp_dif.columns = cellvolt_list df_lipltd_volt_temp_difdif = np.diff(df_lipltd_volt_temp_add,axis=0)#电压二次微分,判断升降 df_lipltd_volt_temp_difdif = pd.DataFrame(df_lipltd_volt_temp_difdif) df_lipltd_volt_temp_difdif.columns = cellvolt_list df_lipltd_volt_temp_difdif_temp = df_lipltd_volt_temp_difdif df_lipltd_volt_temp_difdif_temp[df_lipltd_volt_temp_difdif_temp >= 0] = 1 df_lipltd_volt_temp_difdif_temp[df_lipltd_volt_temp_difdif_temp < 0] = -1 df_lipltd_volt_temp_difdifdif = np.diff(df_lipltd_volt_temp_difdif_temp,axis=0)#三次微分,利用-2,2判断波分和波谷 df_lipltd_volt_difdifdif = pd.DataFrame(df_lipltd_volt_temp_difdifdif) df_lipltd_volt_difdifdif.columns = cellvolt_list df_lipltd_volt_difdifdif['chrgr_rest'] = k df_lipltd_volt_difdifdif['时间戳'] = list(df_check_liplated_temp['时间戳']) df_lipltd_volt_difdifdif = df_lipltd_volt_difdifdif.reset_index(drop = True) df_lipltd_data_temp = df_lipltd_volt_difdifdif.loc[df_lipltd_volt_difdifdif['时间戳'] < (df_check_liplated_temp['时间戳'][0] + datetime.timedelta(minutes=90))] for cell_name in cellvolt_list:#对每个电芯判断 df_check_plated_data = df_lipltd_data_temp[cell_name] peak_pos = np.where(df_check_plated_data == -2) bot_pos = np.where(df_check_plated_data == 2) if len(bot_pos[0]) & len(peak_pos[0]): ini_dvdt = df_check_liplated_temp[cell_name][0] peak_dvdt = df_check_liplated_temp[cell_name][peak_pos[0][0] + 1] bot_dvdt = df_check_liplated_temp[cell_name][bot_pos[0][0] + 1] peak_hight = peak_dvdt - ini_dvdt peak_bot_hight = peak_dvdt - bot_dvdt liplted_amount_temp = (df_check_liplated_temp['时间戳'][bot_pos[0][0] + 1] - df_check_liplated_temp['时间戳'][0])/pd.Timedelta(1, 'min') if ((bot_pos[0][0] - peak_pos[0][0]) > 3) & (df_check_liplated_temp[cell_name][peak_pos[0][0] + 1] < 0) & (peak_bot_hight > 0.05*peak_hight) & (liplted_amount_temp > 15): lipltd_confirm.append(1)#1为析锂,0为非析锂 lipltd_amount.append(liplted_amount_temp) else: lipltd_confirm.append(0) lipltd_amount.append(0) else: lipltd_confirm.append(0) lipltd_amount.append(0) if any(lipltd_confirm): temp = file.split('\\') sn_name = temp[11].split('.')[0] df_lipltd_confir_temp = pd.DataFrame({"sn":[sn_name], "time":[df_check_liplated_temp['时间戳'][0]], "liplated":[str(lipltd_confirm)], "liplated_amount":[str(lipltd_amount)]}) df_lipltd_data = df_lipltd_data.append(df_lipltd_confir_temp) df_lipltd_data = df_lipltd_data.reset_index(drop = True) df_lipltd_data.sort_values(by = ['time'], axis = 0, ascending=True,inplace=True)#对故障信息按照时间进行排序 df_fig_dvdtdata_temp = df_check_liplated_temp df_fig_dvdtdata_temp['chrgr_rest'] = m_num df_fig_dvdtdata = df_fig_dvdtdata.append(df_fig_dvdtdata_temp)#电压对时间微分数据 df_fig_dvdtdata = df_fig_dvdtdata.reset_index(drop = True) df_fig_voltdata_temp = df_check_volt_temp df_fig_voltdata_temp['chrgr_rest'] = m_num df_fig_voltdata = df_fig_voltdata.append(df_fig_voltdata_temp)#原始电压数据 df_fig_voltdata = df_fig_voltdata.reset_index(drop = True) m_num = m_num + 1 df_lipltd_data.to_csv(r'D:\Work\Code_write\data_analyze_platform\USER\lzx\01算法开发\02析锂检测\01下载数据\格林美-Catl7255\析锂检测结果\MGMCLN750N215N155.csv',index=False,encoding='GB18030') df_fig_dvdtdata.to_csv(r'D:\Work\Code_write\data_analyze_platform\USER\lzx\01算法开发\02析锂检测\01下载数据\格林美-Catl7255\析锂检测结果\微分电压曲线.csv',index=False,encoding='GB18030') df_fig_voltdata.to_csv(r'D:\Work\Code_write\data_analyze_platform\USER\lzx\01算法开发\02析锂检测\01下载数据\格林美-Catl7255\析锂检测结果\电压曲线.csv',index=False,encoding='GB18030') for i in range(0,m_num): fig = plt.figure(figsize=(20,10)) df_fig_temp = df_fig_dvdtdata.loc[df_fig_dvdtdata['chrgr_rest'] == i] df_fig_temp = df_fig_temp.reset_index(drop=True) df_fig = df_fig_temp.loc[df_fig_temp['时间戳'] < (df_fig_temp['时间戳'][0] + datetime.timedelta(hours=1))] length = len(df_fig) df_hms_temp = pd.to_datetime(df_fig['时间戳'])#转换时间格式 df_hms = df_hms_temp.dt.time#仅保留时分秒 df_hms_fig = df_hms.apply(lambda x:x.strftime('%H:%M:%S')) for volt_num in cellvolt_name[0:10]: # plt.scatter([x for x in range(0, length)], df_fig[volt_num][0:length], label=volt_num) plt.plot(df_hms_fig, df_fig[volt_num],linewidth = 2, linestyle = '-', marker = 's',label=volt_num) mpl.rcParams['font.sans-serif']=['KaiTi'] mpl.rcParams['axes.unicode_minus']=False #用来正常显示负号 plt.legend() temp = file.split('\\') sn_name = temp[-1].split('.')[0] title = sn_name + '-' + df_fig['时间戳'][0].strftime('%y-%m-%d')#df_fig['device_id'][0] + '-' + plt.xlabel('时间', fontsize=16) plt.ylabel('电压的时间微分(mv/min)', fontsize=16) plt.xticks(range(1,len(df_hms_fig),5),rotation=45, fontsize=16) plt.yticks(fontsize=16) # plt.xlim((df_hms_temp[0]-datetime.timedelta(minutes=5)).dt.time,(df_hms_temp[0] + datetime.timedelta(hours=1.5)).dt.time) # plt.ylim(-2.5,0.5) plt.title(title, fontsize=20) # plt.show() plt.savefig(r'D:\Work\Code_write\data_analyze_platform\USER\lzx\01算法开发\02析锂检测\01下载数据\格林美-Catl7255\析锂分析画图\析锂微分电压曲线\\'+title+'前.png', dpi=300) for i in range(0,m_num): fig = plt.figure(figsize=(20,10)) df_fig_temp = df_fig_dvdtdata.loc[df_fig_dvdtdata['chrgr_rest'] == i] df_fig_temp = df_fig_temp.reset_index(drop=True) df_fig = df_fig_temp.loc[df_fig_temp['时间戳'] < (df_fig_temp['时间戳'][0] + datetime.timedelta(hours=1))] length = len(df_fig) df_hms_temp = pd.to_datetime(df_fig['时间戳'])#转换时间格式 df_hms = df_hms_temp.dt.time#仅保留时分秒 df_hms_fig = df_hms.apply(lambda x:x.strftime('%H:%M:%S')) for volt_num in cellvolt_name[10:21]: # plt.scatter([x for x in range(0, length)], df_fig[volt_num][0:length], label=volt_num) plt.plot(df_hms_fig, df_fig[volt_num],linewidth = 2, linestyle = '-', marker = 's',label=volt_num) mpl.rcParams['font.sans-serif']=['KaiTi'] mpl.rcParams['axes.unicode_minus']=False #用来正常显示负号 plt.legend() temp = file.split('\\') sn_name = temp[-1].split('.')[0] title = sn_name + '-' + df_fig['时间戳'][0].strftime('%y-%m-%d')#df_fig['device_id'][0] + '-' + plt.xlabel('时间', fontsize=16) plt.ylabel('电压的时间微分(mv/min)', fontsize=16) plt.xticks(range(1,len(df_hms_fig),5),rotation=45, fontsize=16) plt.yticks(fontsize=16) # plt.xlim((df_hms_temp[0]-datetime.timedelta(minutes=5)).dt.time,(df_hms_temp[0] + datetime.timedelta(hours=1.5)).dt.time) # plt.ylim(-2.5,0.5) plt.title(title, fontsize=20) # plt.show() plt.savefig(r'D:\Work\Code_write\data_analyze_platform\USER\lzx\01算法开发\02析锂检测\01下载数据\格林美-Catl7255\析锂分析画图\析锂微分电压曲线\\'+title+'后.png', dpi=300) #-------------------------------------原始电压变化曲线------------------------------------------------- fig = plt.figure(figsize=(20,15)) for i in range(0,m_num):#0,k # fig = plt.figure(figsize=(20,10)) df_fig = df_fig_voltdata.loc[df_fig_voltdata['chrgr_rest'] == i] df_fig = df_fig.reset_index(drop=True) length = len(df_fig) temp = file.split('\\') sn_name = temp[-1].split('.')[0] title = sn_name + '-' + df_fig['时间戳'][0].strftime('%y-%m-%d')#df_fig['device_id'][0] + '-' + plt_data_len = len(df_fig) # for volt_num in cellvolt_name[5:6]: # plt.scatter([x for x in range(0, length)], df_fig[volt_num][0:length], label=volt_num) # plt.plot([x for x in range(0, plt_data_len)], df_fig[cellvolt_name[5]],linewidth = 2, linestyle = '-', marker = 's',label = title) plt.plot([x for x in range(0, plt_data_len)], df_fig[cellvolt_name[2]],linewidth = 2, linestyle = '-', marker = 's',label = title) # plt.plot(df_fig['时间戳'], df_fig[cellvolt_name[5]],linewidth = 2, linestyle = '-', marker = 's',label = title)#cellvolt_name[5] mpl.rcParams['font.sans-serif']=['KaiTi'] mpl.rcParams['axes.unicode_minus']=False #用来正常显示负号 plt.legend(fontsize=24) plt.xlabel('采样点', fontsize=24) plt.ylabel('电压(mV)', fontsize=24) plt.xticks(fontsize=20) plt.yticks(fontsize=20) # plt.xlim(df_fig['时间戳'][0]-datetime.timedelta(minutes=5),df_fig['时间戳'][0] + datetime.timedelta(hours=1.5)) # plt.xlim(0, 30) # plt.ylim(4120, 4200) # plt.ylim(-2.5,0.5) plt.title('3#电芯不同时刻电压曲线', fontsize=30) plt.savefig(r'D:\Work\Code_write\data_analyze_platform\USER\lzx\01算法开发\02析锂检测\01下载数据\格林美-Catl7255\析锂分析画图\充电后静置电压曲线\\'+'3#电芯不同时刻电压曲线'+'.png', dpi=300) # # plt.show() # fig = plt.figure(figsize=(20,10)) # for i in range(3,4):#0,k # # fig = plt.figure(figsize=(20,10)) # df_fig = df_rest_volt_diffdt.loc[df_rest_volt_diffdt['chrgr_rest'] == i] # df_fig = df_fig.reset_index(drop=True) # length = len(df_fig) # temp = file.split('\\') # sn_name = temp[9].split('.')[0] # title = sn_name + '-' + df_fig['时间戳'][0].strftime('%y-%m-%d')#df_fig['device_id'][0] + '-' + # plt_data_len = len(df_fig) # # for volt_num in cellvolt_name[5:6]: # # plt.scatter([x for x in range(0, length)], df_fig[volt_num][0:length], label=volt_num) # # plt.plot([x for x in range(0, plt_data_len)], df_fig[cellvolt_name[5]],linewidth = 2, linestyle = '-', marker = 's',label = title) # # plt.plot([x for x in range(0, plt_data_len)], df_fig[cellvolt_name[2]],linewidth = 2, linestyle = '-', marker = 's',label = title) # plt.plot(df_fig['时间戳'], df_fig[cellvolt_name[5]],linewidth = 2, linestyle = '-', marker = 's',label = cellvolt_name[5]) # mpl.rcParams['font.sans-serif']=['SimHei'] # mpl.rcParams['axes.unicode_minus']=False #用来正常显示负号 # plt.legend() # plt.xlabel('采样点', fontsize=14) # plt.ylabel('电压的时间微分(mv/min)', fontsize=14) # plt.xlim(df_fig['时间戳'][0]-datetime.timedelta(minutes=5),df_fig['时间戳'][0] + datetime.timedelta(hours=5)) # # plt.xlim(0, 60) # # plt.ylim(-2.5,0.5) # plt.title('6#电芯不同时间电压微分曲线') # plt.savefig(r'D:\Work\Code_write\data_analyze_platform\USER\lzx\01算法开发\02析锂检测\01下载数据\MGMCLN750N215N049\\'+'6#电芯析锂'+'.png', dpi=300) # plt.show()