From 2f37a7329b6b335e14b6791573842ef34eaa33c3 Mon Sep 17 00:00:00 2001 From: Danila Gamkov Date: Wed, 21 May 2025 14:01:56 +0300 Subject: [PATCH] add python files (impulse_response.py, step_response.py, step_response_diff.py) for extract step and impulse response from experiments with KDI MVN --- asotr.py | 12 ++-- data/.~lock.asotr01_data_T.csv# | 1 - data/.~lock.asotr01_min_T.csv# | 1 + impulse_response.py | 41 ++++++++++++ step_response.py | 67 +++++++++++++++++++ step_response_diff.py | 111 ++++++++++++++++++++++++++++++++ 6 files changed, 224 insertions(+), 9 deletions(-) delete mode 100644 data/.~lock.asotr01_data_T.csv# create mode 100644 data/.~lock.asotr01_min_T.csv# create mode 100644 impulse_response.py create mode 100644 step_response.py create mode 100644 step_response_diff.py diff --git a/asotr.py b/asotr.py index 7c1bef0..0bad743 100644 --- a/asotr.py +++ b/asotr.py @@ -448,10 +448,8 @@ def cut_norm_data(data, time_begin, duration_sec, channel='ch1', def get_step_response_diff(data, thermocycle_info, channel='ch1', interp={'method': 'cubic', 'order': 2}, accuracy='seconds', cut_step_resp={}): - date = thermocycle_info['date'] - - time_begin_orig = date + ' ' + thermocycle_info['time_begin'][0] - time_begin_step = date + ' ' + thermocycle_info['time_begin'][1] + time_begin_orig = thermocycle_info['time_begin'][0] + time_begin_step = thermocycle_info['time_begin'][1] duration_sec = thermocycle_info['duration_sec'] @@ -472,7 +470,7 @@ def get_step_response_diff(data, thermocycle_info, channel='ch1', step_response = pd.DataFrame({'timestamp': step_time, 'temp': step_temp}) if len(cut_step_resp) > 0: - time_begin = date + ' ' + cut_step_resp['time_step_begin'] + time_begin = cut_step_resp['time_step_begin'] try: step_response = cut_data(step_response, time_begin, cut_step_resp['step_duration'], accuracy='seconds') @@ -502,7 +500,7 @@ def plot_step_response_in_thermocycle(data_info, thermocycle_info, interp, ax1.plot(step_resp['timestamp'], step_resp['temp'], label='реакция на ступенчатое воздействие') - step_begin = thermocycle_info['date'] + ' ' + cut_step_resp['time_step_begin'] + step_begin = cut_step_resp['time_step_begin'] idx = find_best_time_idx(step_interp_cycle.timestamp, step_begin, accuracy=data_info['find_accuracy']) @@ -535,8 +533,6 @@ def plot_step_response_in_thermocycle(data_info, thermocycle_info, interp, fig.savefig(plot_info["name_fig"]) plt.show() - - def plot_imp_response(data, data_info, plot_info, thermocycle_info): title = f'{plot_info["title"]}, канал {data_info["channel"][2]} АСОТР КДИ СПИН-X, период опроса {data_info["period"]} ({thermocycle_info["date"]})' diff --git a/data/.~lock.asotr01_data_T.csv# b/data/.~lock.asotr01_data_T.csv# deleted file mode 100644 index 7cbbcf4..0000000 --- a/data/.~lock.asotr01_data_T.csv# +++ /dev/null @@ -1 +0,0 @@ -,danila,danila-IdeaPad,20.05.2025 18:07,file:///home/danila/.config/libreoffice/4; \ No newline at end of file diff --git a/data/.~lock.asotr01_min_T.csv# b/data/.~lock.asotr01_min_T.csv# new file mode 100644 index 0000000..711c536 --- /dev/null +++ b/data/.~lock.asotr01_min_T.csv# @@ -0,0 +1 @@ +,danila,danila-IdeaPad,21.05.2025 11:32,file:///home/danila/.config/libreoffice/4; \ No newline at end of file diff --git a/impulse_response.py b/impulse_response.py new file mode 100644 index 0000000..b63bd8a --- /dev/null +++ b/impulse_response.py @@ -0,0 +1,41 @@ +import pandas as pd +import matplotlib.pyplot as plt +import sys +from importlib import reload +sys.path.append('/home/danila/Danila/work/MVN/Soft/PID/python/') +import asotr +reload(asotr) +import matplotlib.pyplot as plt +from matplotlib import dates +import pandas as pd +from datetime import datetime + +asotr_kit = 1 +fname = f'../python_cyclo/data/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) + +interp = {'method': 'polynomial', 'order': 2} +thermocycle_info = {'date': '14.03.2025', 'type': 'impuse'} +cut_step_resp = {'orig_time_step_begin': '14.03.2025 13:49:32', 'orig_step_duration': 20*60} +data_info = {'data': data, 'channel': 'ch1', 'period': '1 сек', 'find_accuracy': 'seconds'} + +name = f'{thermocycle_info["type"]}_response_{thermocycle_info["date"].replace(".","")}' + +plot_info = {'title': 'Реакция на импульсное воздействие', + 'ox_dtime_format': "%H:%M:%S", 'legend_pos': ['upper right', 'lower left'], + 'name_fig': f'{name}.png', + 'font': 10} + +tstamp_orig_begin = cut_step_resp['orig_time_step_begin'] + +_, interp_imp_resp = asotr.cut_norm_data(data_info['data'], tstamp_orig_begin, + cut_step_resp['orig_step_duration'], channel='ch1', interp=interp, + accuracy=data_info['find_accuracy']) + + +interp_imp_resp.to_csv(f'./data/asotr0{asotr_kit}_{name}.csv', index=False, sep=';', + encoding='utf-8-sig', decimal='.') + +asotr.plot_imp_response(interp_imp_resp, data_info, plot_info, thermocycle_info) diff --git a/step_response.py b/step_response.py new file mode 100644 index 0000000..d4f4a56 --- /dev/null +++ b/step_response.py @@ -0,0 +1,67 @@ +import pandas as pd +import matplotlib.pyplot as plt +import sys +from importlib import reload +sys.path.append('/home/danila/Danila/work/MVN/Soft/PID/python/') +import asotr +reload(asotr) +import matplotlib.pyplot as plt +from matplotlib import dates +import pandas as pd +from datetime import datetime + +asotr_kit = 1 +# fname = f'../python_cyclo/data/asotr0{asotr_kit}_data_T.csv' +fname = f'../python_cyclo/data/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) + +# date = '20.03.2025' +# period = '1 мин' +# time_begin_orig = date + ' 17:10:11' +# time_begin1 = date + ' 18:10:17' +# time_begin2 = date + ' 19:10:23' +# step_begin = time_begin2 +# duration = 3600 +# accuracy = 'seconds' +# name_fig = 'step_response_KDI_20242003.png' + +# date = '21.03.2025' +# period = '1 мин' +# time_begin_orig = date + ' 14:00:11' +# time_begin1 = date + ' 15:00:16' +# time_begin2 = date + ' 16:00:16' +# step_begin = time_begin2 +# duration = 3600 +# accuracy = 'seconds' +# name_fig = 'step_response_KDI_20242103.png' + +# date = '24.03.2025' +# period = '1 сек' +# time_begin_orig = date + ' 19:45:11' +# time_begin1 = date + ' 20:45:13' +# time_begin2 = date + ' 21:45:17' +# step_begin = time_begin2 +# duration = 3600 +# accuracy = 'seconds' +# name_fig = 'step_response_KDI_20242403.png' + + +interp = {'method': 'polynomial', 'order': 2} +thermocycle_info = {'date': '01.04.2025', + 'time_begin': ['01.04.2025 16:27:00', '01.04.2025 18:00:00'], + 'duration_sec': 92*60, 'type': 'step'} +cut_step_resp = {'time_step_begin': '01.04.2025 18:53:21', 'step_duration': 25*60} +data_info = {'data': data, 'device': 'KDI', 'channel': 'ch1', 'period': '1 мин', + 'find_accuracy': 'seconds'} +name = f'{thermocycle_info["type"]}_response_{data_info["device"]}_{thermocycle_info["date"].replace(".","")}' +plot_info = {'title': 'Реакция на ступенчатое воздействие', + 'ox_dtime_format': "%H:%M:%S", 'legend_pos': ['upper left', 'lower left'], + 'name_fig': f'{name}.png', 'font': 10} + +asotr.plot_step_response_in_thermocycle(data_info, thermocycle_info, interp, + cut_step_resp, plot_info) + + + diff --git a/step_response_diff.py b/step_response_diff.py new file mode 100644 index 0000000..090e306 --- /dev/null +++ b/step_response_diff.py @@ -0,0 +1,111 @@ +import pandas as pd +import matplotlib.pyplot as plt +import sys +from importlib import reload +sys.path.append('/home/danila/Danila/work/MVN/Soft/PID/python/') +import asotr +reload(asotr) + +import matplotlib.pyplot as plt +from matplotlib import dates +import pandas as pd +from datetime import datetime + +asotr_kit = 1 +fname = f'../python_cyclo/data/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) + +# date = '20.03.2025' +# period = '1 мин' +# time_begin_orig = date + ' 17:10:11' +# time_begin1 = date + ' 18:10:17' +# time_begin2 = date + ' 19:10:23' +# step_begin = time_begin2 +# duration = 3600 +# accuracy = 'seconds' +# name_fig = 'step_response_KDI_20242003.png' + +# date = '21.03.2025' +# period = '1 мин' +# time_begin_orig = date + ' 14:00:11' +# time_begin1 = date + ' 15:00:16' +# time_begin2 = date + ' 16:00:16' +# step_begin = time_begin2 +# duration = 3600 +# accuracy = 'seconds' +# name_fig = 'step_response_KDI_20242103.png' + +# date = '24.03.2025' +# period = '1 сек' +# time_begin_orig = date + ' 19:45:11' +# time_begin1 = date + ' 20:45:13' +# time_begin2 = date + ' 21:45:17' +# step_begin = time_begin2 +# duration = 3600 +# accuracy = 'seconds' +# name_fig = 'step_response_KDI_20242403.png' + + +# interp = {'method': 'polynomial', 'order': 2} +# thermocycle_info = {'date': '24.03.2025', 'time_begin': ['20:45:00', '21:45:11'], +# 'duration_sec': 60*60, 'type': 'step'} +# cut_step_resp = {'time_step_begin': '21:45:11', 'step_duration': 60*60, +# 'orig_time_step_begin': '19:45:11', 'orig_step_duration': 25*60} +# data_info = {'data': data, 'device': 'KDI', 'channel': 'ch1', 'period': '1 мин', +# 'find_accuracy': 'seconds'} +# name = f'{thermocycle_info["type"]}_response_diff_{data_info["device"]}_{thermocycle_info["date"].replace(".","")}' +# plot_info = {'title': 'Реакция на ступенчатое воздействие', +# 'ox_dtime_format': "%H:%M:%S", 'legend_pos': ['upper left', 'lower left'], +# 'name_fig': f'{name}.png', 'font': 10} + + +interp = {'method': 'polynomial', 'order': 2} +thermocycle_info = {'date': '01.04.2025', + 'time_begin': ['01.04.2025 16:27:00', '01.04.2025 18:00:00'], + 'duration_sec': 92*60, 'type': 'step'} +cut_step_resp = {'time_step_begin': '01.04.2025 18:53:21', 'step_duration': 24*60, + 'orig_time_step_begin': '01.04.2025 15:22:10', 'orig_step_duration': 24*60} +data_info = {'data': data, 'channel': 'ch1', 'period': '1 мин', + 'find_accuracy': 'seconds'} +plot_info = {'title': 'Реакция на ступенч. воздейств.', + 'ox_dtime_format': "%H:%M:%S", 'legend_pos': ['lower right', 'lower left'], + 'name_fig': 'step_response_diff_KDI_20240401.png', 'font': 10} + +step_resp_cut, _, _ = asotr.get_step_response_diff(data_info['data'], thermocycle_info, + channel=data_info['channel'], interp=interp, accuracy=data_info['find_accuracy'], + cut_step_resp=cut_step_resp) + +tstamp_orig_begin = cut_step_resp['orig_time_step_begin'] + +_, interp_step_resp = asotr.cut_norm_data(data_info['data'], tstamp_orig_begin, + cut_step_resp['orig_step_duration'], channel='ch1', interp=interp, + accuracy=data_info['find_accuracy']) + +max_ = min(len(interp_step_resp), len(step_resp_cut)) + +interp_step_resp.to_csv(f'./data/asotr0{asotr_kit}_{thermocycle_info["type"]}_{thermocycle_info["date"].replace(".","")}.csv', index=False, sep=';', encoding='utf-8-sig', decimal='.') + +title = f'{plot_info["title"]}, канал {data_info["channel"][2]} АСОТР КДИ СПИН-X1-МВН, период опроса {data_info["period"]} ({thermocycle_info["date"]})' + +fig = plt.figure(figsize=(6, 6), dpi=200) +fig.suptitle(title, fontsize=plot_info['font']) +ax1 = fig.add_subplot(1,1,1) + +ax1.plot(step_resp_cut['timestamp'].iloc[0:max_], step_resp_cut['temp'].iloc[0:max_], '--', + label='реакция на ступенчатое воздействие с термоциклом') +ax1.plot(step_resp_cut['timestamp'].iloc[0:max_], interp_step_resp['temp'].iloc[0:max_], + label='реакция на ступенчатое воздействие') + +date_formatter = dates.DateFormatter(plot_info['ox_dtime_format']) +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_xlabel('Время', fontsize=plot_info['font']) + +plt.tight_layout() +fig.savefig(plot_info["name_fig"]) +plt.show()