From d91039ca21858e2411277efec314283885d0238a Mon Sep 17 00:00:00 2001 From: Danila Gamkov Date: Thu, 7 Aug 2025 14:13:43 +0300 Subject: [PATCH] plot_flight_borders: add flags for flexibility. tm_wheel_parser.py: plot data distribution --- .gitignore | 1 + README.markdown | 2 + bin/asotr.py | 14 +- bin/asotr_kdi.py | 207 +++++++++++++ bin/kdi_noize.py | 32 ++ bin/plot_asotr_flight_all_for_Mikhail.py | 180 ++++++++++++ bin/plot_data.py | 115 ++++++++ bin/plot_flight_borders.py | 34 ++- bin/step_response.py | 359 ++++++++++++----------- bin/step_response_diff.py | 2 +- bin/tm_brd_parser.py | 8 +- bin/tm_wheel_parser.py | 68 ++++- 12 files changed, 820 insertions(+), 202 deletions(-) create mode 100644 bin/asotr_kdi.py create mode 100644 bin/kdi_noize.py create mode 100644 bin/plot_asotr_flight_all_for_Mikhail.py create mode 100644 bin/plot_data.py diff --git a/.gitignore b/.gitignore index 25e9882..3cdd63d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.csv +*.xml *.png *.swp *.swo diff --git a/README.markdown b/README.markdown index 593c6cd..4b33d12 100644 --- a/README.markdown +++ b/README.markdown @@ -28,6 +28,8 @@ This project contains tools for decoding, converting, and visualizing telemetry -> `/plots/` — folder where output plots are saved. ## Requirements +- git + - Python version 3.10 or upper. For checking type: ```bash python3 --version diff --git a/bin/asotr.py b/bin/asotr.py index 0b89898..aee746b 100644 --- a/bin/asotr.py +++ b/bin/asotr.py @@ -445,7 +445,7 @@ def cut_norm_data(data, time_begin, duration_sec, channel='ch1', orig_data = pd.DataFrame({ 'timestamp': time_l, 'temp': temp_l }) interp_data = orig_data.set_index('timestamp') - interp_data = interp_data.resample('S').mean().interpolate(method=interp["method"], + interp_data = interp_data.resample('s').mean().interpolate(method=interp["method"], order=interp["order"]) interp_data = interp_data.reset_index(names=['timestamp']) @@ -498,7 +498,7 @@ def plot_step_response_in_thermocycle(data_info, thermocycle_info, interp, data_info['data'], thermocycle_info, channel=data_info['channel'], interp=interp, accuracy=data_info['find_accuracy']) - fig = plt.figure(figsize=(9, 6), dpi=200) + fig = plt.figure(figsize=(8, 7), dpi=200) fig.suptitle(title, fontsize=plot_info['font']) ax1 = fig.add_subplot(2,1,1) ax2 = fig.add_subplot(2,1,2) @@ -510,6 +510,10 @@ def plot_step_response_in_thermocycle(data_info, thermocycle_info, interp, idx = find_best_time_idx(step_interp_cycle.timestamp, step_begin, accuracy=data_info['find_accuracy']) + if idx == -1: + print(f'index corresponding to time {step_begin} in times array not found!') + return + ax1.axvline(x = step_interp_cycle.timestamp[idx], color='r', linestyle='-.', label= thermocycle_info['type_ru'] + ' воздействие, начало') @@ -531,8 +535,8 @@ def plot_step_response_in_thermocycle(data_info, thermocycle_info, interp, fancybox=True, framealpha=0.4) ax2.grid(True) ax2.tick_params(axis='both', width=1, labelsize=plot_info['font']) - ax2.set_xlabel('Время, ЧЧ:MM:CC', fontsize=plot_info['font']) - ax2.set_ylabel(r'$T_{norm}$, $^\circ$C', fontsize=plot_info['font']) + ax2.set_xlabel('Время, ЧЧ:MM', fontsize=plot_info['font']) + ax2.set_ylabel(r'$T_{норм}$, $^\circ$C', fontsize=plot_info['font']) fig.suptitle(title, fontsize=plot_info['font']) plt.tight_layout() @@ -555,7 +559,7 @@ def plot_imp_response(data, data_info, plot_info, thermocycle_info): ax1.grid(True) ax1.tick_params(axis='both', width=1, labelsize=plot_info['font']) ax1.set_xlabel('время', fontsize=plot_info['font']) - ax1.set_ylabel(r'$t_{norm}$, $^\circ$C', fontsize=plot_info['font']) + ax1.set_ylabel(r'$t_{норм}$, $^\circ$C', fontsize=plot_info['font']) fig.suptitle(title, fontsize=plot_info['font']) plt.tight_layout() diff --git a/bin/asotr_kdi.py b/bin/asotr_kdi.py new file mode 100644 index 0000000..0525837 --- /dev/null +++ b/bin/asotr_kdi.py @@ -0,0 +1,207 @@ +import sys +from importlib import reload +sys.path.append('./') +import asotr +reload(asotr) +import matplotlib.pyplot as plt +from matplotlib import dates +import pandas as pd +from datetime import datetime, timedelta +import os +import json + +def cmd_parse(asotr_data): + decode_list = [] + + for elem in asotr_data.itertuples(): + elem_msg = asotr.cmd_decode(elem.cmd.strip()) + if elem_msg != '': + str_ = f'{elem.timestamp};{elem_msg}' + decode_list.append(str_) + + return decode_list + +def pow_temp_parse(elem, tstamp_format='%d.%m.%Y %H:%M:%S.%f'): + timestamp = pd.to_datetime(elem.timestamp, format=tstamp_format) + if "*1" not in elem.data: + return ('none', []) + l = [] + + data = elem.data[2:] + l = [] + l.append(asotr.get_utc_seconds(elem.timestamp, tstamp_format)) + l.append(timestamp) + + if "status 3" in elem.cmd: + l.extend(list(map(float, data.split()))) + return ('t', l) + elif "status 4" in elem.cmd: + l.extend(list(map(int, data.split()))) + return ('p', l) + else: + return ('none', []) + +def get_cmd_data(fname, tstamp_format='%d.%m.%Y %H:%M:%S.%f'): + t = [] + p = [] + asotr_data = pd.read_csv(fname, delimiter=';', names=['timestamp', 'cmd', 'data']) + + cmd_list = cmd_parse(asotr_data) + + for elem in asotr_data.itertuples(): + data = pow_temp_parse(elem, tstamp_format) + if data[0] == 't': + t.append(data[1]) + elif data[0] == 'p': + p.append(data[1]) + temp = pd.DataFrame(t, + columns=['timestamp_sec', 'timestamp', 'ch1', 'ch2', 'ch3', 'ch4', 'ch5', 'ch6']) + power = pd.DataFrame(p, + columns=['timestamp_sec', 'timestamp', 'ch1', 'ch2', 'ch3', 'ch4', 'ch5', 'ch6']) + return (cmd_list, temp, power) + + +def decode_collect_data(uart_server_log_path, asotr_kit): + files = os.listdir(uart_server_log_path) + files1 = [file for file in files if 'cmd_data' in file] + files1 = sorted(files1) + + cmd_list_itog = [] + temp_itog = [] + pow_itog = [] + + cmd_list, temp, power = get_cmd_data(uart_server_log_path + files1[0]) + cmd_list_itog.extend(cmd_list) + temp_itog = temp + pow_itog = power + print(files1[0]) + + for i, file in enumerate(files1): + if i > 0: + print(file) + cmd_list, temp, power = get_cmd_data(uart_server_log_path + file) + cmd_list_itog.extend(cmd_list) + temp_itog = pd.concat([temp_itog, temp], ignore_index=True) + pow_itog = pd.concat([pow_itog, power], ignore_index=True) + + temp_itog = temp_itog.sort_values(by='timestamp_sec') + pow_itog = pow_itog.sort_values(by='timestamp_sec') + + temp_itog['timestamp'] = temp_itog['timestamp'].dt.strftime('%d.%m.%Y %H:%M:%S.%f') + pow_itog['timestamp'] = pow_itog['timestamp'].dt.strftime('%d.%m.%Y %H:%M:%S.%f') + + temp_itog.to_csv(f'./data/asotr0{asotr_kit}_data_T.csv', index=False, sep=';', + encoding='utf-8-sig', decimal='.') + pow_itog.to_csv(f'./data/asotr0{asotr_kit}_data_P.csv', index=False, sep=';', + encoding='utf-8-sig', decimal='.') + + with open('./data/cmd_human.csv', 'w') as file: + for elem in cmd_list_itog: + file.write(f'{elem}\n') + + +def load_ps_cmd_decode(fname): + with open(fname, 'r') as file: + ps_cmd_decode = json.load(file) + return ps_cmd_decode + +def get_ps_cmd_data(fname, ps_model): + decode = load_ps_cmd_decode('./decode_ps_cmd.json') + ps_data = pd.read_csv(fname, sep=';', names=['timestamp', 'cmd', 'cmd_answer']) + out = {'cmd_write': [], 'cmd_read': [], 'cmd_read_desc': []} + + if ps_model == 'PSH-3630A': + for elem in decode: + if elem['ps_model'] == ps_model: + decode_cmd_write = elem['cmd_write'] + decode_cmd_read = elem['cmd_read'] + decode_cmd_read_desc = elem['cmd_read_desc'] + break + + cmd_write = [] + cmd_read_desc = [] + cmd_read = [] + for row in ps_data.itertuples(): + # check if current row is cmd_write: + cmd_str = row.cmd.split(' ') + + timestamp_sec = asotr.get_utc_seconds(row.timestamp, '%d.%m.%Y %H:%M:%S.%f') + if (len(cmd_str) > 1): + elem = [timestamp_sec, row.timestamp, + decode_cmd_write[cmd_str[0]], cmd_str[1]] + cmd_write.append(elem) + elif (len(cmd_str) == 1): + elem = [timestamp_sec, row.timestamp, + decode_cmd_read[cmd_str[0]], row.cmd_answer.strip()] + cmd_read.append(elem) + elem = [timestamp_sec, row.timestamp, + decode_cmd_read_desc[cmd_str[0]], row.cmd_answer.strip()] + cmd_read_desc.append(elem) + + out['cmd_write'] = cmd_write + out['cmd_read'] = cmd_read + out['cmd_read_desc'] = cmd_read_desc + + return out + +def convert_data_date_format(directory, fname_pattern, column_names, + old_date_fmt = "%Y.%m.%d %H:%M:%S.%f", + new_date_fmt = '%d.%m.%Y %H:%M:%S.%f'): + + files = os.listdir(directory) + dateparse = lambda x: datetime.strptime(x, old_date_fmt) + + for file in files: + fname = directory + file + if 'cmd_data' in fname: + print(fname) + df = pd.read_csv(fname, sep=';', decimal='.', + names=column_names, + parse_dates=['timestamp'], date_parser=dateparse) + + df['timestamp'] = df['timestamp'].dt.strftime(new_date_fmt) + + df.to_csv(fname, header=False, index=False, sep=';', + decimal='.', encoding='utf-8-sig') + + +def plot_data(fname, title, ox_dtime_format, events={}, hlines={}, ch='ch1'): + cmd_list, temp, power = get_cmd_data(fname) + + fig = plt.figure(figsize=(10, 8), dpi=150) + ax1 = fig.add_subplot(2,1,1) + ax2 = fig.add_subplot(2,1,2, sharex=ax1) + + ax1.plot(temp.timestamp, temp[ch]) + + if len(hlines) > 0: + for label, value in hlines.items(): + ax1.axhline(y = value, color='b', linestyle='--') + ax1.text(temp.timestamp[len(temp.timestamp) - 1], value, label, va='bottom') + + if len(events) > 0: + for time, event in events.items(): + idx = asotr.find_best_time_idx(temp.timestamp, time, accuracy='seconds') + ax1.axvline(x = temp.timestamp[idx], color='r', linestyle='-.') + ax1.text(temp.timestamp[idx], max(temp[ch]) + 1, event, rotation=45, va='bottom') + + ax2.plot(power.timestamp, power[ch]) + + date_formatter = dates.DateFormatter(ox_dtime_format) + + ax1.xaxis.set_major_formatter(date_formatter) + ax1.set_xlabel('время') + ax1.set_ylabel('Температура, $^\circ$C') + ax1.grid(True) + + ax2.xaxis.set_major_formatter(date_formatter) + ax2.set_ylabel('Мощность, %') + ax2.grid(True) + + fig.suptitle(title) + plt.legend() + plt.tight_layout() + fig.savefig('plot_experim_data.png') + plt.show() + + diff --git a/bin/kdi_noize.py b/bin/kdi_noize.py new file mode 100644 index 0000000..12282c3 --- /dev/null +++ b/bin/kdi_noize.py @@ -0,0 +1,32 @@ +import sys +from importlib import reload +sys.path.append('./') +import asotr_kdi +import asotr +reload(asotr_kdi) +reload(asotr) + +fname = '/home/danila/Danila/work/MVN/Soft/PID/rust/uart_server/log_experim/cmd_data_asotr/asotr01/cmd_data_20250314_asotr.log' + +# fname = '/home/danila/Danila/work/MVN/Soft/PID/rust/uart_server/log_experim/cmd_data_asotr/asotr01/cmd_data_20250324_asotr_step_var_cond.log' + +# fname = '/home/danila/Danila/work/MVN/Soft/PID/rust/uart_server/log_experim/cmd_data_asotr/asotr01/cmd_data_20250325_asotrPD_thermostat.log' + +# fname_save = '../data/experiments/noize_20250325_12.csv' +# begin_time = '25.03.2025 11:55:00' +# end_time = '25.03.2025 12:10:00' + +fname_save = '../data/experiments/noize_20250314_14.csv' +begin_time = '14.03.2025 14:20:00' +end_time = '14.03.2025 14:35:00' + +cmd_list, temp, power = asotr_kdi.get_cmd_data(fname) + +begin = asotr.find_best_time_idx(temp.timestamp, begin_time, accuracy='seconds') +end = asotr.find_best_time_idx(temp.timestamp, end_time, accuracy='seconds') + +temp1 = temp[begin:end] + +print(temp1) +temp1.to_csv(fname_save, date_format='%d.%m.%Y %H:%M:%S.%f', index=False, sep=';', columns=['timestamp', 'ch1', 'ch2', 'ch3', 'ch4', 'ch5', 'ch6']) + diff --git a/bin/plot_asotr_flight_all_for_Mikhail.py b/bin/plot_asotr_flight_all_for_Mikhail.py new file mode 100644 index 0000000..d381ae7 --- /dev/null +++ b/bin/plot_asotr_flight_all_for_Mikhail.py @@ -0,0 +1,180 @@ +import matplotlib.pyplot as plt +from matplotlib import dates +import pandas as pd +from datetime import datetime +import sys + +font = 14 +print_width = 15 +print_height = 8 +plot_windows = 2 +channels = [1, 0, 0, 0, 0, 0] +asotr_kit = '01' + +xborders=False +begin=0; +end=0; + +path = '../data/asotr/' +fname_B = f'{path}beta_2025.xlsx' + +fname = 'asotr' + asotr_kit + '_data_T.csv' +fname_pow = 'asotr' + asotr_kit + '_data_P.csv' + +pict_name = '../plots/' + 'ASOTR' + asotr_kit + '_flight_T_P_all' +ox_dtime_format = '%Y.%m.%d' + +legend=['БРД1', 'БРД2', 'БРД3', 'БРД4', 'плита МУП МВН, датчик1', 'плита МУП МВН, датчик 2'] +width=[1, 2, 1, 1, 1, 1] + +marker = ['-', '--', '-', '-', '-.', '-']; +width_arr = [1, 0.5, 0.2, 0.1, 1, 1] + +data_b = pd.read_excel(fname_B, + sheet_name=0, + usecols=[0,1,2], + header=4, + names=['turn_num', 'beta_angle', 'timestamp'], + parse_dates=['timestamp'], + date_format='%Y-%m-%d %H:%M:%S') + + +fname = [path + fname, path + fname_pow] +data = [pd.read_csv(fname[0], sep=';', parse_dates=['timestamp'], date_format="%d.%m.%Y %H:%M:%S.%f"), + pd.read_csv(fname[1], sep=';', parse_dates=['timestamp'], date_format="%d.%m.%Y %H:%M:%S.%f")] + +ch= [[], [], [], [], [], []] +ch_signs = ["temp", "pow"] +data_dict = {"temp": ch, "pow": ch, "time": []} +data_dict["time"] = data[0]['timestamp'] +col=['ch1', 'ch2', 'ch3', 'ch4', 'ch5', 'ch6', 'ch7'] + +for j in range(2): + for index, row, in data[j].iterrows(): + for i in range(6): + ch[i].append(float(row[col[i]])) + data_dict[ch_signs[j]] = ch + ch= [[], [], [], [], [], []] + +len_data = [len(data_dict['temp'][0]), len(data_dict['pow'][0])] +len_ = min(len_data) + +if xborders == False: + begin = 0 + end = len_ - 1 + + + +if plot_windows == 1: + fig, ax = plt.subplots(figsize=(print_width, print_height), dpi=300) + + i = 0 + for elem in data_dict['temp']: + if channels[i] == 1: + ax.plot(data_dict['time'][begin:end], elem[begin:end], marker[i], linewidth=width[i], label=legend[i]) + i += 1 + + ax.tick_params(axis="both", width=1, labelsize=font) + ax.grid(visible=True, linestyle = 'dotted') + ax.set_ylabel(r"Температура, $^\circ$C", fontsize=font) + ax.set_xlabel('Время', fontsize=font) + ax.legend(fontsize=font) + + date_formatter = dates.DateFormatter(ox_dtime_format) + ax.xaxis.set_major_formatter(date_formatter) + + plt.tight_layout() + fig.savefig(pict_name) + plt.show() + +elif plot_windows == 2: + + fig = plt.figure(figsize=(print_width, print_height), dpi=600) + ax1 = fig.add_subplot(1, 1, 1) + # ax2 = fig.add_subplot(2, 1, 2, sharex=ax1) + + i = 0 + for elem in data_dict['temp']: + if channels[i] == 1: + ax1.plot(data_dict['time'][begin:end], elem[begin:end], marker[i], linewidth=width[i], label=legend[i]) + i += 1 + + ax3 = ax1.twinx() + ax3.plot(data_b['timestamp'][0:3400], data_b['beta_angle'][0:3400], marker[1], color='r', linewidth=width[1], label='угол Бета') + ax3.set_ylabel('Угол Бета', fontsize=font) + ax3.tick_params(axis="y", width=1, labelsize=font) + ax3.legend(fontsize=font, loc='upper right') + + # i = 0 + # for elem in data_dict['pow']: + # if channels[i] == 1: + # ax2.plot(data_dict['time'][begin:end], elem[begin:end], marker[i], linewidth=width[i], label=legend[i]) + # i += 1 + + ax1.tick_params(axis="both", width=1, labelsize=font) + ax1.grid(visible=True, linestyle = 'dotted') + ax1.set_ylabel(r"Температура, $^\circ$C", fontsize=font) + ax1.set_xlabel('Время', fontsize=font) + ax1.legend(fontsize=font, loc='lower right') + + date_formatter = dates.DateFormatter(ox_dtime_format) + ax1.xaxis.set_major_formatter(date_formatter) + + # ax2.tick_params(axis="both", width=1, labelsize=font) + # ax2.grid(visible=True, linestyle = 'dotted') + # ax2.set_ylabel('Мощность, %', fontsize=font) + # ax2.set_xlabel('Время', fontsize=font) + # ax2.legend(fontsize=font, loc='lower right') + + # date_formatter = dates.DateFormatter(ox_dtime_format) + # ax2.xaxis.set_major_formatter(date_formatter) + + plt.title('АСОТР ' + asotr_kit, fontsize=font) + plt.tight_layout() + fig.savefig(pict_name) + plt.show() + + + + + +# asotr_kit2 = '02' +# fname2 = 'asotr' + asotr_kit2 + '_data_T.csv' +# fname_pow2 = 'asotr' + asotr_kit2 + '_data_P.csv' +# legend2=['2 БРД1', '2 БРД2', '2 БРД3', '2 БРД4', '2 плита МУП МВН, датчик1', '2 плита МУП МВН, датчик 2'] + +# fname2 = [path + fname2, path + fname_pow2] +# data2 = [pd.read_csv(fname2[0], sep=';', parse_dates=['timestamp'], date_parser=dateparse), +# pd.read_csv(fname2[1], sep=';', parse_dates=['timestamp'], date_parser=dateparse)] + +# ch= [[], [], [], [], [], []] +# ch_signs = ["temp", "pow"] +# data_dict2 = {"temp": ch, "pow": ch, "time": []} +# data_dict2["time"] = data2[0]['timestamp'] +# col=['ch1', 'ch2', 'ch3', 'ch4', 'ch5', 'ch6', 'ch7'] + +# for j in range(2): +# for index, row, in data2[j].iterrows(): +# for i in range(6): +# ch[i].append(float(row[col[i]])) +# data_dict2[ch_signs[j]] = ch +# ch= [[], [], [], [], [], []] + +# len_data2 = [len(data_dict2['temp'][0]), len(data_dict2['pow'][0])] +# len_2 = min(len_data2) + +# if xborders == False: +# begin2 = 0 +# end2 = len_2 - 1 + + +# i = 0 +# for elem in data_dict2['temp']: +# if channels[i] == 1: +# print('legend2: ' + legend2[i]) +# ax1.plot(data_dict2['time'][begin2:end2], elem[begin2:end2], marker[i], linewidth=width[i], label=legend2[i]) +# i += 1 + + # ax2.plot(pd.Series(data_dict2['temp'][0]) - pd.Series(data_dict['temp'][0])) + + diff --git a/bin/plot_data.py b/bin/plot_data.py new file mode 100644 index 0000000..1cd2a9c --- /dev/null +++ b/bin/plot_data.py @@ -0,0 +1,115 @@ +import sys +from importlib import reload +sys.path.append('./') +import asotr_kdi +reload(asotr_kdi) +import matplotlib.pyplot as plt +import pandas as pd +import re + +ox_dtime_format = "%H:%M:%S" +ch = 'ch4' +# fname = '~/Danila/work/MVN/Soft/PID/rust/uart_server/log/cmd_data_20250311.log' +# fname = '~/Danila/work/MVN/Soft/PID/rust/uart_server/log/cmd_data_20250311.log' + +# events = [] +# hlines = [] +# date = '17.03.2025' +# fname = '~/Danila/work/MVN/Soft/PID/rust/uart_server/log_experim/cmd_data_asotr/asotr01/cmd_data_20250317_asotrD_thermostat.log' +# title = f'Эксперименты по настройке ПД-регулятора на канале {ch[2]} АСОТР КДИ СПИН-X ({date})' + +# hlines = { +# 'Туст. = 27': 27, +# 'Туст. = 29': 29, +# 'Туст. = 31': 31, +# } + +# events = { +# '17.03.2025 12:50:14': 'Kp=0, Kd=2000, Ki=0, Туст.=29', +# '17.03.2025 13:20:18': 'запрет работы ПИД', +# '17.03.2025 14:15:14': 'Kp=0, Kd=2000, Ki=0, Туст.=31', +# '17.03.2025 14:45:18': 'запрет работы ПИД', +# '17.03.2025 15:41:14': 'Kp=50, Kd=2000, Ki=0, Туст.=31', +# '17.03.2025 16:11:17': 'запрет работы ПИД', +# '17.03.2025 17:05:13': 'Kp=50, Kd=2000, Ki=0, Туст.=27', +# '17.03.2025 17:50:17': 'запрет работы ПИД', +# '17.03.2025 19:30:10': 'Kp=100, Kd=2000, Ki=0, Туст.=27', +# '17.03.2025 20:15:13': 'запрет работы ПИД', +# } + +# date = '16.04.2025' +# fname = '/home/danila/Danila/work/MVN/Soft/PID/rust/uart_server/log_experim/cmd_data_20250416_asotrPID_thermostat.log' +# title = f'Проверка работы ПИД-регулятора (Kp=615, Ki=0.000115, Kd=1300), канал {ch[2]} АСОТР КДИ СПИН-X ({date})' + +# hlines = { +# '27': 27, +# '27.5': 27.5, +# '28': 28, +# '29': 29 +# } + +# events = { +# '16.04.2025 15:45:11': 'Туст=27', +# '16.04.2025 16:15:15': 'Туст=27.5', +# '16.04.2025 16:45:18': 'Туст=28', +# '16.04.2025 17:15:22': 'Туст=29', +# } + + +events = [] +hlines = [] + +date = '14.03.2025' +title = f'Эксперименты с АСОТР КДИ СПИН-X ({date})' +fname = '/home/danila/Danila/work/MVN/Soft/PID/rust/uart_server/log_experim/cmd_data_asotr/asotr01/cmd_data_20250314_asotr.log' + + +# date = '20.03.2025' +# title = f'Эксперименты с АСОТР КДИ СПИН-X ({date})' +# fname = '/home/danila/Danila/work/MVN/Soft/PID/rust/uart_server/log_experim/cmd_data_asotr/asotr01/cmd_data_20250320_asotr_step_var_cond.log' + +# date = '21.03.2025' +# title = f'Эксперименты с АСОТР КДИ СПИН-X ({date})' +# fname = '/home/danila/Danila/work/MVN/Soft/PID/rust/uart_server/log_experim/cmd_data_asotr/asotr01/cmd_data_20250321_asotr_step_var_cond.log' + +# date = '24.03.2025' +# title = f'Эксперименты с АСОТР КДИ СПИН-X ({date})' +# fname = '/home/danila/Danila/work/MVN/Soft/PID/rust/uart_server/log_experim/cmd_data_asotr/asotr01/cmd_data_20250324_asotr_step_var_cond.log' + +# date = '01.04.2025' +# title = f'Эксперименты с АСОТР КДИ СПИН-X ({date})' +# fname = '/home/danila/Danila/work/MVN/Soft/PID/rust/uart_server/log_experim/cmd_data_asotr/asotr01/cmd_data_20250401_asotr_step_var_cond.log' +# title = f'эксперимент по подаче ступенчатого воздействия на канал {ch[2]} АСОТР КДИ СПИН-X в различных условиях ({date})' + +# hlines = { +# 'Туст. = 27': 27, +# 'Туст. = 26': 26 +# } + +# events = { +# '25.03.2025 11:25:00': 'Kp=200, Kd=2000, Ki=0, Туст.=27', +# '25.03.2025 12:10:14': 'запрет работы ПИД', +# '25.03.2025 12:30:00': 'Kp=200, Kd=2000, Ki=0, Туст.=26', +# '25.03.2025 13:15:14': 'запрет работы ПИД', +# } + +# date = '25.03.2025' +# title = f'Эксперименты по настройке ПД-регулятора на канале {ch[2]} АСОТР КДИ СПИН-X ({date})' +# fname = '~/Danila/work/MVN/Soft/PID/rust/uart_server/log_experim/cmd_data_asotr/asotr01/cmd_data_20250325_asotrPD_thermostat.log' + +# hlines = { +# 'Туст. = 26': 26 +# } + +# events = { +# # '26.03.2025 16:15:11': 'Kp=200, Kd=2000, Ki=0, Туст.=26', +# # '26.03.2025 18:45:30': 'запрет работы ПИД', +# } + +# date = '26.03.2025' +# title = f'Эксперименты по настройке ПД-регулятора на канале {ch[2]} АСОТР КДИ СПИН-X ({date})' +# fname = '~/Danila/work/MVN/Soft/PID/rust/uart_server/log_experim/cmd_data_asotr/asotr01/cmd_data_20250326_asotrPD_thermostat.log' + +asotr_kdi.plot_data(fname, title, ox_dtime_format, events, hlines, ch) + + diff --git a/bin/plot_flight_borders.py b/bin/plot_flight_borders.py index 1b81a65..d0989d1 100644 --- a/bin/plot_flight_borders.py +++ b/bin/plot_flight_borders.py @@ -8,17 +8,17 @@ import asotr reload(asotr) import pandas as pd -def plot_asotr_borders(path_with_data, ch, asotr_kit, begin, end, font=14, cmd=0, show_flag=True): +def plot_asotr_borders(path_with_data, ch, asotr_kit, begin, end, font=12, cmd=0, + show_flag=False, plot_windows=2, width_=1, time_format='%d.%m.%Y'): print_width = 20 print_height = 12 - width = 1 - plot_windows = 2 channels = list(map(int, ch)) pict_name = (f'../plots/reports/ASOTR{asotr_kit}_flight_T_P_{asotr.convert_to_str(channels)}_{begin[0:5].replace(".", "")}_{end[0:5].replace(".", "")}.png') plot_task = {"temp": 1, "temp_set": 1, "pow": 1} - ox_dtime_format = "%d.%m.%Y" + # ox_dtime_format = "%d.%m.%Y" + ox_dtime_format = time_format legend = [ "канал 1 (БРД1)", @@ -29,10 +29,10 @@ def plot_asotr_borders(path_with_data, ch, asotr_kit, begin, end, font=14, cmd=0 "канал 6 (плита МУП МВН)", ] legend_set = list(map(lambda x: x + " уставка", legend)) - width = [1, 1, 1, 1, 1, 1] + width = [width_, width_, width_, width_, width_, width_] width_set = [3, 3, 3, 3, 3, 3] - marker = ["-", "--", "-.", "-", "-", "--"] + marker = ["-", "-", "-.", "-", "-", "--"] width_arr = [1, 0.5, 0.2, 0.1, 1, 1] # get from files and prepare data @@ -44,7 +44,7 @@ def plot_asotr_borders(path_with_data, ch, asotr_kit, begin, end, font=14, cmd=0 return if plot_windows == 1: - fig, ax = plt.subplots(figsize=(print_width, print_height), dpi=200) + fig, ax = plt.subplots(figsize=(print_width, print_height), dpi=300) if plot_task["temp"] == 1: for i in range(len(channels)): @@ -72,7 +72,7 @@ def plot_asotr_borders(path_with_data, ch, asotr_kit, begin, end, font=14, cmd=0 elif plot_windows == 2: - fig = plt.figure(figsize=(print_width, print_height), dpi=200) + fig = plt.figure(figsize=(print_width, print_height), dpi=300) ax1 = fig.add_subplot(2, 1, 1) ax2 = fig.add_subplot(2, 1, 2, sharex=ax1) @@ -173,10 +173,20 @@ if __name__ == '__main__': argparser.add_argument('-f', '--font', required=False, help='type font size (from 1 to 30)') argparser.add_argument('-d', '--cmd', required=False, - help='type display commands flag (0/1)') + help='type display commands flag (0 or 1)') argparser.add_argument('-p', '--plot', required=False, - help='display data in plot flag (0/1)') + help='display data in plot flag (0 or 1)') + argparser.add_argument('-w', '--plotwindows', required=False, + help='plot counts in window (1 or 2)') + argparser.add_argument('-l', '--linewidth', required=False, + help='line width in plot (1, 2, ...)') + argparser.add_argument('-t', '--timeformat', required=False, + help='specify the time format, for example: %d.%m.%Y') + args = argparser.parse_args() - plot_asotr_borders(args.source, args.channel, args.asotr, args.begin, args.end, - args.font, args.cmd, show_flag=args.plot) + # plot_asotr_borders(args.source, args.channel, args.asotr, args.begin, args.end, + # args.font, args.cmd, show_flag=args.plot, plot_windows=int(args.plotwindows), + # width_=int(args.linewidth), time_format = args.timeformat) + + plot_asotr_borders(args.source, args.channel, args.asotr, args.begin, args.end) diff --git a/bin/step_response.py b/bin/step_response.py index 00c325a..11758ce 100644 --- a/bin/step_response.py +++ b/bin/step_response.py @@ -11,11 +11,8 @@ import pandas as pd from datetime import datetime asotr_kit = 1 -# fname = f'../python_cyclo/data/asotr0{asotr_kit}_data_T.csv' fname = f'../data/asotr/asotr0{asotr_kit}_data_T.csv' - -dateparse = lambda x: datetime.strptime(x, "%d.%m.%Y %H:%M:%S.%f") -data = pd.read_csv(fname, sep=';', parse_dates=['timestamp'], date_parser=dateparse) +data = pd.read_csv(fname, sep=';', parse_dates=["timestamp"], date_format="%d.%m.%Y %H:%M:%S.%f") # date = '20.03.2025' # period = '1 мин' @@ -48,7 +45,6 @@ data = pd.read_csv(fname, sep=';', parse_dates=['timestamp'], date_parser=datepa # name_fig = 'step_response_KDI_20242403.png' - # interp = {'method': 'polynomial', 'order': 1} # thermocycle_info = {'date': '01.04.2025', # 'time_begin': ['01.04.2025 16:27:00', '01.04.2025 18:00:00'], @@ -62,6 +58,8 @@ data = pd.read_csv(fname, sep=';', parse_dates=['timestamp'], date_parser=datepa # 'name_fig': f'{name}.png', 'font': 10} +fname = f'../../python_cyclo/data/asotr0{asotr_kit}_data_T.csv' +data = pd.read_csv(fname, sep=';', parse_dates=["timestamp"], date_format="%d.%m.%Y %H:%M:%S.%f") interp = {'method': 'polynomial', 'order': 1} @@ -69,46 +67,12 @@ data_info_list = [] thermocycle_info_list = [] cut_step_resp_list = [] -data_info = {'data': data, 'device': 'летный', 'channel': 'ch1', 'period': '1 мин', +data_info = {'data': data, 'device': 'КДИ', 'channel': 'ch1', 'period': '1 мин', 'find_accuracy': 'seconds'} -thermocycle_info = {'date': '25.04.2025', - 'time_begin': ['24.04.2025 22:46:32', '25.04.2025 00:19:33'], +thermocycle_info = {'date': '01.04.2025', + 'time_begin': ['01.04.2025 16:27:13', '01.04.2025 18:00:18'], 'duration_sec': 92*60, 'type': 'step', 'type_ru': 'ступенчатое'} -cut_step_resp = {'time_step_begin': '25.04.2025 01:18:01', 'step_duration': 30*60} - -data_info_list.append(data_info) -thermocycle_info_list.append(thermocycle_info) -cut_step_resp_list.append(cut_step_resp) - -data_info = {'data': data, 'device': 'летный', 'channel': 'ch2', 'period': '1 мин', - 'find_accuracy': 'seconds'} -thermocycle_info = {'date': '25.04.2025', - 'time_begin': ['24.04.2025 22:46:32', '25.04.2025 00:19:33'], - 'duration_sec': 92*60, 'type': 'step1_to2', 'type_ru': 'ступенчатое'} -cut_step_resp = {'time_step_begin': '25.04.2025 01:18:01', 'step_duration': 30*60} - -data_info_list.append(data_info) -thermocycle_info_list.append(thermocycle_info) -cut_step_resp_list.append(cut_step_resp) - - -data_info = {'data': data, 'device': 'летный', 'channel': 'ch1', 'period': '1 мин', - 'find_accuracy': 'seconds'} -thermocycle_info = {'date': '25.04.2025', - 'time_begin': ['25.04.2025 01:52:34', '25.04.2025 03:25:34'], - 'duration_sec': 92*60, 'type': 'impulse', 'type_ru': 'импульсное'} -cut_step_resp = {'time_step_begin': '25.04.2025 04:24:00', 'step_duration': 15*60} - -data_info_list.append(data_info) -thermocycle_info_list.append(thermocycle_info) -cut_step_resp_list.append(cut_step_resp) - -data_info = {'data': data, 'device': 'летный', 'channel': 'ch2', 'period': '1 мин', - 'find_accuracy': 'seconds'} -thermocycle_info = {'date': '25.04.2025', - 'time_begin': ['25.04.2025 01:52:34', '25.04.2025 03:25:34'], - 'duration_sec': 92*60, 'type': 'impulse1_to2', 'type_ru': 'импульсное'} -cut_step_resp = {'time_step_begin': '25.04.2025 04:24:00', 'step_duration': 20*60} +cut_step_resp = {'time_step_begin': '01.04.2025 18:53:20', 'step_duration': 25*60} data_info_list.append(data_info) thermocycle_info_list.append(thermocycle_info) @@ -116,144 +80,199 @@ cut_step_resp_list.append(cut_step_resp) -data_info = {'data': data, 'device': 'летный', 'channel': 'ch2', 'period': '1 мин', - 'find_accuracy': 'seconds'} -thermocycle_info = {'date': '30.04.2025', - 'time_begin': ['29.04.2025 22:02:54', '29.04.2025 23:35:54'], - 'duration_sec': 93*60, 'type': 'step', 'type_ru': 'ступенчатое'} -cut_step_resp = {'time_step_begin': '30.04.2025 00:36:01', 'step_duration': 30*60} - -data_info_list.append(data_info) -thermocycle_info_list.append(thermocycle_info) -cut_step_resp_list.append(cut_step_resp) - -data_info = {'data': data, 'device': 'летный', 'channel': 'ch1', 'period': '1 мин', - 'find_accuracy': 'seconds'} -thermocycle_info = {'date': '30.04.2025', - 'time_begin': ['29.04.2025 22:02:54', '29.04.2025 23:35:54'], - 'duration_sec': 93*60, 'type': 'step2_to1', 'type_ru': 'ступенчатое'} -cut_step_resp = {'time_step_begin': '30.04.2025 00:36:01', 'step_duration': 30*60} - -data_info_list.append(data_info) -thermocycle_info_list.append(thermocycle_info) -cut_step_resp_list.append(cut_step_resp) - -data_info = {'data': data, 'device': 'летный', 'channel': 'ch2', 'period': '1 мин', - 'find_accuracy': 'seconds'} -thermocycle_info = {'date': '30.04.2025', - 'time_begin': ['30.04.2025 01:09:55', '30.04.2025 02:41:54'], - 'duration_sec': 93*60, 'type': 'impulse', 'type_ru': 'импульсное'} -cut_step_resp = {'time_step_begin': '30.04.2025 03:42:00', 'step_duration': 15*60} - -data_info_list.append(data_info) -thermocycle_info_list.append(thermocycle_info) -cut_step_resp_list.append(cut_step_resp) - -data_info = {'data': data, 'device': 'летный', 'channel': 'ch1', 'period': '1 мин', - 'find_accuracy': 'seconds'} -thermocycle_info = {'date': '30.04.2025', - 'time_begin': ['30.04.2025 01:09:55', '30.04.2025 02:41:54'], - 'duration_sec': 93*60, 'type': 'impulse2_to1', 'type_ru': 'импульсное'} -cut_step_resp = {'time_step_begin': '30.04.2025 03:42:00', 'step_duration': 20*60} - -data_info_list.append(data_info) -thermocycle_info_list.append(thermocycle_info) -cut_step_resp_list.append(cut_step_resp) - -data_info = {'data': data, 'device': 'летный', 'channel': 'ch4', 'period': '1 мин', - 'find_accuracy': 'seconds'} -thermocycle_info = {'date': '02.05.2025', - 'time_begin': ['01.05.2025 22:05:30', '01.05.2025 23:38:40'], - 'duration_sec': 93*60, 'type': 'step', 'type_ru': 'ступенчатое'} -cut_step_resp = {'time_step_begin': '02.05.2025 00:39:00', 'step_duration': 30*60} - -data_info_list.append(data_info) -thermocycle_info_list.append(thermocycle_info) -cut_step_resp_list.append(cut_step_resp) - -data_info = {'data': data, 'device': 'летный', 'channel': 'ch3', 'period': '1 мин', - 'find_accuracy': 'seconds'} -thermocycle_info = {'date': '02.05.2025', - 'time_begin': ['01.05.2025 22:05:30', '01.05.2025 23:38:40'], - 'duration_sec': 93*60, 'type': 'step4_to3', 'type_ru': 'ступенчатое'} -cut_step_resp = {'time_step_begin': '02.05.2025 00:39:00', 'step_duration': 30*60} - -data_info_list.append(data_info) -thermocycle_info_list.append(thermocycle_info) -cut_step_resp_list.append(cut_step_resp) - -data_info = {'data': data, 'device': 'летный', 'channel': 'ch4', 'period': '1 мин', - 'find_accuracy': 'seconds'} -thermocycle_info = {'date': '02.05.2025', - 'time_begin': ['02.05.2025 01:12:30', '02.05.2025 02:46:02'], - 'duration_sec': 93*60, 'type': 'impulse', 'type_ru': 'импульсное'} -cut_step_resp = {'time_step_begin': '02.05.2025 03:45:02', 'step_duration': 15*60} - -data_info_list.append(data_info) -thermocycle_info_list.append(thermocycle_info) -cut_step_resp_list.append(cut_step_resp) - -data_info = {'data': data, 'device': 'летный', 'channel': 'ch3', 'period': '1 мин', - 'find_accuracy': 'seconds'} -thermocycle_info = {'date': '02.05.2025', - 'time_begin': ['02.05.2025 01:12:30', '02.05.2025 02:46:02'], - 'duration_sec': 93*60, 'type': 'impulse4_to3', 'type_ru': 'импульсное'} -cut_step_resp = {'time_step_begin': '02.05.2025 03:45:02', 'step_duration': 20*60} - -data_info_list.append(data_info) -thermocycle_info_list.append(thermocycle_info) -cut_step_resp_list.append(cut_step_resp) -data_info = {'data': data, 'device': 'летный', 'channel': 'ch3', 'period': '1 мин', - 'find_accuracy': 'seconds'} -thermocycle_info = {'date': '04.05.2025', - 'time_begin': ['03.05.2025 22:12:11', '03.05.2025 23:45:10'], - 'duration_sec': 93*60, 'type': 'step', 'type_ru': 'ступенчатое'} -cut_step_resp = {'time_step_begin': '04.05.2025 00:42:01', 'step_duration': 26*60} +# interp = {'method': 'polynomial', 'order': 1} -data_info_list.append(data_info) -thermocycle_info_list.append(thermocycle_info) -cut_step_resp_list.append(cut_step_resp) +# data_info_list = [] +# thermocycle_info_list = [] +# cut_step_resp_list = [] -data_info = {'data': data, 'device': 'летный', 'channel': 'ch4', 'period': '1 мин', - 'find_accuracy': 'seconds'} -thermocycle_info = {'date': '04.05.2025', - 'time_begin': ['03.05.2025 22:12:11', '03.05.2025 23:45:10'], - 'duration_sec': 93*60, 'type': 'step3_to4', 'type_ru': 'ступенчатое'} -cut_step_resp = {'time_step_begin': '04.05.2025 00:42:01', 'step_duration': 30*60} +# data_info = {'data': data, 'device': 'летный', 'channel': 'ch1', 'period': '1 мин', +# 'find_accuracy': 'seconds'} +# thermocycle_info = {'date': '25.04.2025', +# 'time_begin': ['24.04.2025 22:46:32', '25.04.2025 00:19:33'], +# 'duration_sec': 92*60, 'type': 'step', 'type_ru': 'ступенчатое'} +# cut_step_resp = {'time_step_begin': '25.04.2025 01:18:01', 'step_duration': 30*60} -data_info_list.append(data_info) -thermocycle_info_list.append(thermocycle_info) -cut_step_resp_list.append(cut_step_resp) +# data_info_list.append(data_info) +# thermocycle_info_list.append(thermocycle_info) +# cut_step_resp_list.append(cut_step_resp) -data_info = {'data': data, 'device': 'летный', 'channel': 'ch3', 'period': '1 мин', - 'find_accuracy': 'seconds'} -thermocycle_info = {'date': '04.05.2025', - 'time_begin': ['04.05.2025 01:19:10', '04.05.2025 02:52:11'], - 'duration_sec': 93*60, 'type': 'impulse', 'type_ru': 'импульсное'} -cut_step_resp = {'time_step_begin': '04.05.2025 03:48:01', 'step_duration': 15*60} +# data_info = {'data': data, 'device': 'летный', 'channel': 'ch2', 'period': '1 мин', +# 'find_accuracy': 'seconds'} +# thermocycle_info = {'date': '25.04.2025', +# 'time_begin': ['24.04.2025 22:46:32', '25.04.2025 00:19:33'], +# 'duration_sec': 92*60, 'type': 'step1_to2', 'type_ru': 'ступенчатое'} +# cut_step_resp = {'time_step_begin': '25.04.2025 01:18:01', 'step_duration': 30*60} -data_info_list.append(data_info) -thermocycle_info_list.append(thermocycle_info) -cut_step_resp_list.append(cut_step_resp) +# data_info_list.append(data_info) +# thermocycle_info_list.append(thermocycle_info) +# cut_step_resp_list.append(cut_step_resp) -data_info = {'data': data, 'device': 'летный', 'channel': 'ch4', 'period': '1 мин', - 'find_accuracy': 'seconds'} -thermocycle_info = {'date': '04.05.2025', - 'time_begin': ['04.05.2025 01:19:10', '04.05.2025 02:52:11'], - 'duration_sec': 93*60, 'type': 'impulse3_to4', 'type_ru': 'импульсное'} -cut_step_resp = {'time_step_begin': '04.05.2025 03:48:01', 'step_duration': 20*60} -data_info_list.append(data_info) -thermocycle_info_list.append(thermocycle_info) -cut_step_resp_list.append(cut_step_resp) +# data_info = {'data': data, 'device': 'летный', 'channel': 'ch1', 'period': '1 мин', +# 'find_accuracy': 'seconds'} +# thermocycle_info = {'date': '25.04.2025', +# 'time_begin': ['25.04.2025 01:52:34', '25.04.2025 03:25:34'], +# 'duration_sec': 92*60, 'type': 'impulse', 'type_ru': 'импульсное'} +# cut_step_resp = {'time_step_begin': '25.04.2025 04:24:00', 'step_duration': 15*60} + +# data_info_list.append(data_info) +# thermocycle_info_list.append(thermocycle_info) +# cut_step_resp_list.append(cut_step_resp) + +# data_info = {'data': data, 'device': 'летный', 'channel': 'ch2', 'period': '1 мин', +# 'find_accuracy2: 'seconds'} +# thermocycle_info = {'date': '25.04.2025', +# 'time_begin': ['25.04.2025 01:52:34', '25.04.2025 03:25:34'], +# 'duration_sec': 92*60, 'type': 'impulse1_to2', 'type_ru': 'импульсное'} +# cut_step_resp = {'time_step_begin': '25.04.2025 04:24:00', 'step_duration': 20*60} + +# data_info_list.append(data_info) +# thermocycle_info_list.append(thermocycle_info) +# cut_step_resp_list.append(cut_step_resp) + + + +# data_info = {'data': data, 'device': 'летный', 'channel': 'ch2', 'period': '1 мин', +# 'find_accuracy': 'seconds'} +# thermocycle_info = {'date': '30.04.2025', +# 'time_begin': ['29.04.2025 22:02:54', '29.04.2025 23:35:54'], +# 'duration_sec': 93*60, 'type': 'step', 'type_ru': 'ступенчатое'} +# cut_step_resp = {'time_step_begin': '30.04.2025 00:36:01', 'step_duration': 30*60} + +# data_info_list.append(data_info) +# thermocycle_info_list.append(thermocycle_info) +# cut_step_resp_list.append(cut_step_resp) + +# data_info = {'data': data, 'device': 'летный', 'channel': 'ch1', 'period': '1 мин', +# 'find_accuracy': 'seconds'} +# thermocycle_info = {'date': '30.04.2025', +# 'time_begin': ['29.04.2025 22:02:54', '29.04.2025 23:35:54'], +# 'duration_sec': 93*60, 'type': 'step2_to1', 'type_ru': 'ступенчатое'} +# cut_step_resp = {'time_step_begin': '30.04.2025 00:36:01', 'step_duration': 30*60} + +# data_info_list.append(data_info) +# thermocycle_info_list.append(thermocycle_info) +# cut_step_resp_list.append(cut_step_resp) + +# data_info = {'data': data, 'device': 'летный', 'channel': 'ch2', 'period': '1 мин', +# 'find_accuracy': 'seconds'} +# thermocycle_info = {'date': '30.04.2025', +# 'time_begin': ['30.04.2025 01:09:55', '30.04.2025 02:41:54'], +# 'duration_sec': 93*60, 'type': 'impulse', 'type_ru': 'импульсное'} +# cut_step_resp = {'time_step_begin': '30.04.2025 03:42:00', 'step_duration': 15*60} + +# data_info_list.append(data_info) +# thermocycle_info_list.append(thermocycle_info) +# cut_step_resp_list.append(cut_step_resp) + +# data_info = {'data': data, 'device': 'летный', 'channel': 'ch1', 'period': '1 мин', +# 'find_accuracy': 'seconds'} +# thermocycle_info = {'date': '30.04.2025', +# 'time_begin': ['30.04.2025 01:09:55', '30.04.2025 02:41:54'], +# 'duration_sec': 93*60, 'type': 'impulse2_to1', 'type_ru': 'импульсное'} +# cut_step_resp = {'time_step_begin': '30.04.2025 03:42:00', 'step_duration': 20*60} + +# data_info_list.append(data_info) +# thermocycle_info_list.append(thermocycle_info) +# cut_step_resp_list.append(cut_step_resp) + +# data_info = {'data': data, 'device': 'летный', 'channel': 'ch4', 'period': '1 мин', +# 'find_accuracy': 'seconds'} +# thermocycle_info = {'date': '02.05.2025', +# 'time_begin': ['01.05.2025 22:05:30', '01.05.2025 23:38:40'], +# 'duration_sec': 93*60, 'type': 'step', 'type_ru': 'ступенчатое'} +# cut_step_resp = {'time_step_begin': '02.05.2025 00:39:00', 'step_duration': 30*60} + +# data_info_list.append(data_info) +# thermocycle_info_list.append(thermocycle_info) +# cut_step_resp_list.append(cut_step_resp) + +# data_info = {'data': data, 'device': 'летный', 'channel': 'ch3', 'period': '1 мин', +# 'find_accuracy': 'seconds'} +# thermocycle_info = {'date': '02.05.2025', +# 'time_begin': ['01.05.2025 22:05:30', '01.05.2025 23:38:40'], +# 'duration_sec': 93*60, 'type': 'step4_to3', 'type_ru': 'ступенчатое'} +# cut_step_resp = {'time_step_begin': '02.05.2025 00:39:00', 'step_duration': 30*60} + +# data_info_list.append(data_info) +# thermocycle_info_list.append(thermocycle_info) +# cut_step_resp_list.append(cut_step_resp) + +# data_info = {'data': data, 'device': 'летный', 'channel': 'ch4', 'period': '1 мин', +# 'find_accuracy': 'seconds'} +# thermocycle_info = {'date': '02.05.2025', +# 'time_begin': ['02.05.2025 01:12:30', '02.05.2025 02:46:02'], +# 'duration_sec': 93*60, 'type': 'impulse', 'type_ru': 'импульсное'} +# cut_step_resp = {'time_step_begin': '02.05.2025 03:45:02', 'step_duration': 15*60} + +# data_info_list.append(data_info) +# thermocycle_info_list.append(thermocycle_info) +# cut_step_resp_list.append(cut_step_resp) + +# data_info = {'data': data, 'device': 'летный', 'channel': 'ch3', 'period': '1 мин', +# 'find_accuracy': 'seconds'} +# thermocycle_info = {'date': '02.05.2025', +# 'time_begin': ['02.05.2025 01:12:30', '02.05.2025 02:46:02'], +# 'duration_sec': 93*60, 'type': 'impulse4_to3', 'type_ru': 'импульсное'} +# cut_step_resp = {'time_step_begin': '02.05.2025 03:45:02', 'step_duration': 20*60} + +# data_info_list.append(data_info) +# thermocycle_info_list.append(thermocycle_info) +# cut_step_resp_list.append(cut_step_resp) + + +# data_info = {'data': data, 'device': 'летный', 'channel': 'ch3', 'period': '1 мин', +# 'find_accuracy': 'seconds'} +# thermocycle_info = {'date': '04.05.2025', +# 'time_begin': ['03.05.2025 22:12:11', '03.05.2025 23:45:10'], +# 'duration_sec': 93*60, 'type': 'step', 'type_ru': 'ступенчатое'} +# cut_step_resp = {'time_step_begin': '04.05.2025 00:42:01', 'step_duration': 26*60} + +# data_info_list.append(data_info) +# thermocycle_info_list.append(thermocycle_info) +# cut_step_resp_list.append(cut_step_resp) + +# data_info = {'data': data, 'device': 'летный', 'channel': 'ch4', 'period': '1 мин', +# 'find_accuracy': 'seconds'} +# thermocycle_info = {'date': '04.05.2025', +# 'time_begin': ['03.05.2025 22:12:11', '03.05.2025 23:45:10'], +# 'duration_sec': 93*60, 'type': 'step3_to4', 'type_ru': 'ступенчатое'} +# cut_step_resp = {'time_step_begin': '04.05.2025 00:42:01', 'step_duration': 30*60} + +# data_info_list.append(data_info) +# thermocycle_info_list.append(thermocycle_info) +# cut_step_resp_list.append(cut_step_resp) + +# data_info = {'data': data, 'device': 'летный', 'channel': 'ch3', 'period': '1 мин', +# 'find_accuracy': 'seconds'} +# thermocycle_info = {'date': '04.05.2025', +# 'time_begin': ['04.05.2025 01:19:10', '04.05.2025 02:52:11'], +# 'duration_sec': 93*60, 'type': 'impulse', 'type_ru': 'импульсное'} +# cut_step_resp = {'time_step_begin': '04.05.2025 03:48:01', 'step_duration': 15*60} + +# data_info_list.append(data_info) +# thermocycle_info_list.append(thermocycle_info) +# cut_step_resp_list.append(cut_step_resp) + +# data_info = {'data': data, 'device': 'летный', 'channel': 'ch4', 'period': '1 мин', +# 'find_accuracy': 'seconds'} +# thermocycle_info = {'date': '04.05.2025', +# 'time_begin': ['04.05.2025 01:19:10', '04.05.2025 02:52:11'], +# 'duration_sec': 93*60, 'type': 'impulse3_to4', 'type_ru': 'импульсное'} +# cut_step_resp = {'time_step_begin': '04.05.2025 03:48:01', 'step_duration': 20*60} + +# data_info_list.append(data_info) +# thermocycle_info_list.append(thermocycle_info) +# cut_step_resp_list.append(cut_step_resp) def get_step_response(data_info, thermocycle_info, cut_step_resp): name = f'{data_info["channel"]}_{thermocycle_info["type"]}_response_{data_info["device"]}_{thermocycle_info["date"].replace(".","")}' plot_info = {'title': 'Реакция на ' + thermocycle_info['type_ru'] + ' воздействие', - 'ox_dtime_format': "%H:%M:%S", 'legend_pos': ['upper left', 'lower left'], + 'ox_dtime_format': "%H:%M", 'legend_pos': ['upper left', 'lower left'], 'name_fig': f'../plots/response/{name}.png', 'font': 10} asotr.plot_step_response_in_thermocycle(data_info, thermocycle_info, interp, @@ -270,7 +289,7 @@ def get_step_response(data_info, thermocycle_info, cut_step_resp): title = f'{plot_info["title"]}, канал {data_info["channel"][2]} АСОТР, {data_info["device"]} СПИН-X1-МВН, период опроса {data_info["period"]} ({thermocycle_info["date"]})' - fig = plt.figure(figsize=(10, 6), dpi=200) + fig = plt.figure(figsize=(6, 10), dpi=200) fig.suptitle(title, fontsize=plot_info['font']) ax1 = fig.add_subplot(1,1,1) @@ -282,8 +301,8 @@ def get_step_response(data_info, thermocycle_info, cut_step_resp): ax1.legend(loc=plot_info["legend_pos"][0], fontsize=plot_info['font']) ax1.grid(True) ax1.tick_params(axis='both', width=1, labelsize=plot_info['font']) - ax1.set_ylabel(r'$T_{norm}$, $^\circ$C', fontsize=plot_info['font']) - ax1.set_xlabel('Время, ЧЧ:MM:CC', fontsize=plot_info['font']) + ax1.set_ylabel(r'$T_{норм}$, $^\circ$C', fontsize=plot_info['font']) + ax1.set_xlabel('Время, ЧЧ:MM', fontsize=plot_info['font']) plt.tight_layout() fig.savefig(plot_info["name_fig"]) diff --git a/bin/step_response_diff.py b/bin/step_response_diff.py index 8fdb62d..f108eef 100644 --- a/bin/step_response_diff.py +++ b/bin/step_response_diff.py @@ -102,7 +102,7 @@ ax1.xaxis.set_major_formatter(date_formatter) ax1.legend(loc=plot_info["legend_pos"][0], fontsize=plot_info['font']) ax1.grid(True) ax1.tick_params(axis='both', width=1, labelsize=plot_info['font']) -ax1.set_ylabel(r'$T_{norm}$, $^\circ$C', fontsize=plot_info['font']) +ax1.set_ylabel(r'$T_{норм}$, $^\circ$C', fontsize=plot_info['font']) ax1.set_xlabel('Время', fontsize=plot_info['font']) plt.tight_layout() diff --git a/bin/tm_brd_parser.py b/bin/tm_brd_parser.py index 792fd03..aa352e3 100644 --- a/bin/tm_brd_parser.py +++ b/bin/tm_brd_parser.py @@ -15,7 +15,7 @@ path_itog_brd_data = '../data/brd_data/' class PathFileNotFound(Exception): pass - +# recursive search files by pattern in specified directory def find_required_files(root_dir, pattern): result = [] for dirpath, _, filenames in os.walk(root_dir): @@ -30,7 +30,7 @@ def find_required_files(root_dir, pattern): return sorted(result) - +# read all finded files into pandas dataFrame def read_files_into_df(fname_list, column_list, dtype_columns={}): data_itog = pd.DataFrame() epoch_start = pd.Timestamp('2000-01-01') @@ -89,7 +89,7 @@ if __name__ == "__main__": column_list = ['TIME', 'PER_1Hz', 'ST_HV'] column_list_itog = ['TIME', 'timestamp', 'PER_1Hz', 'ST_HV'] - collect_tm_brd_files(root_dir_tm_data, column_list, column_list_itog) + # collect_tm_brd_files(root_dir_tm_data, column_list, column_list_itog) ## plot 'evolution' 1 Hz from tm brd data print('plot evolution 1 Hz from tm brd data') @@ -97,5 +97,7 @@ if __name__ == "__main__": fname = path_itog_brd_data + 'mvn_tm_brd01.csv' df = pd.read_csv(fname, sep=';', parse_dates=['timestamp'], date_format="%d.%m.%Y %H:%M:%S.%f") + # print(df) plt.plot(df['timestamp'], df['PER_1Hz'], '.') + plt.grid() plt.show() diff --git a/bin/tm_wheel_parser.py b/bin/tm_wheel_parser.py index 296d0f7..ffee8c0 100644 --- a/bin/tm_wheel_parser.py +++ b/bin/tm_wheel_parser.py @@ -3,13 +3,18 @@ import os import re from pathlib import Path import matplotlib.pyplot as plt +from matplotlib import dates from datetime import datetime, timedelta import sys +import seaborn as sns tstamp_s = '%d.%m.%Y %H:%M:%S.%f' -ox_dtime_format = '%d.%m.%Y %H:%M' +ox_dtime_format = '%H:%M' +ox_date_format = '%d.%m.%Y' path_itog_brd_data = '../data/brd_data/' +pict_name = '../plots/' + 'MVN_wheel' +font = 16 class PathFileNotFound(Exception): @@ -92,23 +97,64 @@ if __name__ == "__main__": column_list = ['TIME', 'STATE'] column_list_itog = ['TIME', 'timestamp', 'STATE'] - collect_tm_brd_wheel_data(root_dir_wheel_data, column_list, column_list_itog) + # collect_tm_brd_wheel_data(root_dir_wheel_data, column_list, column_list_itog) ## parse and plot wheel csv data print('parse and plot wheel csv data') - border_clr_wheel = 2 + border_clr_wheel = 1 fname = path_itog_brd_data + 'mvn_wheel_brd01.csv' - wheel_df = pd.read_csv(fname, sep=';') + wheel_df = pd.read_csv(fname, sep=';', parse_dates=['timestamp'], date_format="%d.%m.%Y %H:%M:%S.%f") + ## diff between 0 and 0 - 30 sec wheel_df['TIME_diff'] = wheel_df['TIME'].diff() - median_tdiff = wheel_df['TIME_diff'].median() - wheel_df_clear = wheel_df[(wheel_df['TIME_diff'] > median_tdiff - border_clr_wheel) & - (wheel_df['TIME_diff'] < median_tdiff + border_clr_wheel)] + ## sampling decimation in order to get period 60 sec + wheel_df = wheel_df.iloc[1::2] + wheel_df['TIME_period'] = wheel_df['TIME'].diff() + # print(wheel_df) + median_tdiff = wheel_df['TIME_period'].median() + # print(median_tdiff) - wheel_df_peaks = wheel_df[(wheel_df['TIME_diff'] <= median_tdiff - border_clr_wheel) | - (wheel_df['TIME_diff'] >= median_tdiff + border_clr_wheel)] + ## discard outliers of the measured wheel period + wheel_df = wheel_df[ + (wheel_df['TIME_period'] > median_tdiff - border_clr_wheel) & + (wheel_df['TIME_period'] < median_tdiff + border_clr_wheel)] + + median = wheel_df['TIME_period'].median() + + rows, cols = wheel_df.shape + median = pd.Series([median] * rows) + + date_format = dates.DateFormatter(ox_date_format) + datetime_format = dates.DateFormatter(ox_dtime_format) + + fig, axes = plt.subplots(3, 1, figsize=(18, 20), dpi=300, height_ratios=[1, 1, 1]) + + axes[0].plot(wheel_df['timestamp'], wheel_df['TIME_period'], '.', + markersize=5) + axes[0].plot(wheel_df['timestamp'], median) + axes[0].set_title("") + axes[0].set_xlabel("Время (ДД.MM.ГГГГ)", fontsize=font) + axes[0].set_ylabel("Полупериод, сек", fontsize=font) + axes[0].grid(True) + axes[0].xaxis.set_major_formatter(date_format) + axes[0].tick_params(axis="both", width=1, labelsize=font) + + axes[1].plot(wheel_df['timestamp'][0:400], wheel_df['TIME_period'][0:400], '.', markersize=10) + axes[1].set_title("") + axes[1].set_xlabel("Время (ЧЧ:ММ)", fontsize=font) + axes[1].set_ylabel("Полупериод, сек", fontsize=font) + axes[1].grid(True) + axes[1].xaxis.set_major_formatter(datetime_format) + axes[1].tick_params(axis="both", width=1, labelsize=font) + + sns.histplot(wheel_df['TIME_period'], kde=False, bins=300, ax=axes[2], color='red') + axes[2].set_title("") + axes[2].set_xlabel("Полупериод, сек", fontsize=font) + axes[2].set_ylabel("Частота встречаемости", fontsize=font) + axes[2].grid(True) + axes[2].tick_params(axis="both", width=1, labelsize=font) + + fig.savefig(pict_name) - plt.plot(wheel_df_clear['TIME'], wheel_df_clear['TIME_diff'], '-') - plt.plot(wheel_df_peaks['TIME'], wheel_df_peaks['TIME_diff'], '.') plt.show()