呼吸代谢监测:代码

呼吸代谢监测系统的实现原理可以看「呼吸代谢监测:原理」这篇文章,这里不多做介绍。

数据采集

气体流量采集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class get_flow_thread(QThread):
def __init__(self, ser, error, x_data, y_data, lock, unlock):
super(get_flow_thread, self).__init__()
self.ser = ser

self.error = error # 流量传感器平均误差
self.threshold = 0.05 # 阈值,用来过滤流量传感器误差

self.x_data = x_data
self.y_data = y_data
self.lock = lock
self.unlock = unlock

self.tic = time.time()

def run(self):
while True:
self.get_data()

def get_data(self):

def ATPS_to_STPD(s):
# 百帕hPa to mmHg
# https://industrial.panasonic.cn/ea/presureunit
# https://www.sojson.com/convert/pressure.html
def transform_mmHg(p):
p = p * 0.750065
return p

e_temperature = 34 # COSMED systems assume the temperature of expired air to be 34C.
pB = transform_mmHg(1008) # 来源天气,单位hPa百帕,要转化成mmHg
pH2O = 39.9 # 单位mmHg,34度气体温度对应100%水蒸气含量压力
x1 = 273 / (273 + e_temperature) # 273K = 0C
x2 = (pB - pH2O) / 760 # 760mmHg 标准大气压
STPD_factor = x1 * x2
s = s * STPD_factor
return s
# N线程锁定
self.lock.lock()
try:
sensor_value = self.ser.readline()
result = ATPS_to_STPD(float(sensor_value) - self.error) # 流量传感器在没有气体流动的情况下也存在读数,所以要校准
y = result if abs(self.y_data[-1] - result) > self.threshold else self.y_data[-1] # 如果新的读值与上一个值的差距小于阈值则放弃新读值
except Exception as e:
# 没有对传感器数据进行校验,所以串口读取的值可能是字符串,字符串无法to float,所以需要手动赋值
# 一般来说会手动赋予上一个值,如果数据为空也就是第一次出现无法 to float时,则=0
y = self.y_data[-1] if len(self.y_data) != 0 else 0
# print(e)

toc = time.time()
x = toc - self.tic

self.x_data.append(x)
self.y_data.append(y)
# N+1线程解锁
self.unlock.unlock()

气体浓度采集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class get_gas_thread(QThread):
def __init__(self, ser, environment, x_data, y_data, lock, unlock):
super(get_gas_thread, self).__init__()
self.ser = ser
self.environment = environment # 环境的O2、CO2浓度
self.x_data = x_data
self.y_data = y_data
self.lock = lock
self.unlock = unlock

self.tic = time.time()

def run(self):
while True:
self.get_data()

def get_data(self):
self.lock.lock()
try:
sensor_value = self.ser.readline()
y = float(sensor_value)
except Exception as e:
y = self.y_data[-1] if len(self.y_data) != 0 else self.environment # 如果是字符串,则赋予上一个值,如果数据长度为0则直接赋予环境浓度
# print(e)

toc = time.time()
x = toc - self.tic

self.x_data.append(x)
self.y_data.append(y)
self.unlock.unlock()

数据计算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
class calculate_thread(QThread):
def __init__(self, e_O2, e_CO2,
x_data, VO2_data, VCO2_data, RQ_data,
O2_data, CO2_data, flow_data, lock, unlock):
super(calculate_thread, self).__init__()

self.e_O2 = e_O2
self.e_CO2 = e_CO2
self.x_data = x_data
self.VO2_data = VO2_data
self.VCO2_data = VCO2_data
self.RQ_data = RQ_data
self.O2_data = O2_data
self.CO2_data = CO2_data
self.flow_data = flow_data
self.lock = lock
self.unlock = unlock

self.tic = time.time()
self.flow_win = np.zeros(1800) # 取 3min 的气体流量作为平均数,也意味着 3min 后才能测得真实数据

def run(self):
while True:
self.calculate()

def calculate(self):
global VO2
global RQ
global EE
global Ve

self.lock.lock()
toc = time.time()

def average():
self.flow_win[:-1] = self.flow_win[1:] # 移动
self.flow_win[-1] = self.flow_data[-1] # 将新值写入
return np.mean(self.flow_win)

fi_O2 = self.e_O2 # 吸入空气O2浓度
fi_CO2 = self.e_CO2 # 吸入空气CO2浓度
fe_O2 = self.O2_data[-1] # 呼出气体O2浓度
fe_CO2 = self.CO2_data[-1] # 呼出气体O2浓度
Ve = average()

fi_O2 /= 100 # 20 -> 20%
fi_CO2 /= 100
fe_O2 /= 100
fe_CO2 /= 100

fi_N2 = 1 - fi_O2 - fi_CO2 # 计算吸入空气中和呼出气体的N2浓度
fe_N2 = 1 - fe_O2 - fe_CO2
Vi = Ve * fe_N2 / fi_N2 # 由于人体不与N2发生反应,所以N2的量是不变的,根据这个计算吸入气流量
VO2 = (Vi * fi_O2) - (Ve * fe_O2) # 计算O2消耗速率,由于Ve的单位(传感器的单位)是L/min,所以耗氧量也是L/min
VCO2 = (Ve * fe_CO2) - (Vi * fi_CO2) # 计算CO2产生速率

# VO2 != 0 ? VCO2/VO2 : 0
# RQ = VCO2 / VO2 if VO2 != 0 else 0

if VO2 > 0.01 and VCO2 > 0.01: # 呼吸的时候才计算RQ,其他时候计算出来的RQ没有意义
RQ = VCO2 / VO2 # RQ呼吸商=RER呼吸交换率
else:
RQ = 0

def calculate_EE(a, b): # O2与EE对应关系
z = 0
if round(a, 2) < 0.71:
z = 4.686 * b
elif round(a, 2) == 0.71:
z = 4.69 * b
elif round(a, 2) == 0.72:
z = 4.702 * b
elif round(a, 2) == 0.73:
z = 4.714 * b
elif round(a, 2) == 0.74:
z = 4.727 * b
elif round(a, 2) == 0.75:
z = 4.738 * b
elif round(a, 2) == 0.76:
z = 4.751 * b
elif round(a, 2) == 0.77:
z = 4.764 * b
elif round(a, 2) == 0.78:
z = 4.776 * b
elif round(a, 2) == 0.79:
z = 4.788 * b
elif round(a, 2) == 0.80:
z = 4.801 * b
elif round(a, 2) == 0.81:
z = 4.813 * b
elif round(a, 2) == 0.82:
z = 4.825 * b
elif round(a, 2) == 0.83:
z = 4.838 * b
elif round(a, 2) == 0.84:
z = 4.85 * b
elif round(a, 2) == 0.85:
z = 4.862 * b
elif round(a, 2) == 0.86:
z = 4.875 * b
elif round(a, 2) == 0.87:
z = 4.887 * b
elif round(a, 2) == 0.88:
z = 4.899 * b
elif round(a, 2) == 0.89:
z = 4.911 * b
elif round(a, 2) == 0.90:
z = 4.924 * b
elif round(a, 2) == 0.91:
z = 4.936 * b
elif round(a, 2) == 0.92:
z = 4.948 * b
elif round(a, 2) == 0.93:
z = 4.961 * b
elif round(a, 2) == 0.94:
z = 4.973 * b
elif round(a, 2) == 0.95:
z = 4.985 * b
elif round(a, 2) == 0.96:
z = 4.998 * b
elif round(a, 2) == 0.97:
z = 5.01 * b
elif round(a, 2) == 0.98:
z = 5.022 * b
elif round(a, 2) == 0.99:
z = 5.035 * b
elif round(a, 2) > 0.99:
z = 5.047 * b
return z

EE = calculate_EE(RQ, VO2)
x = toc - self.tic
self.x_data.append(x)
self.VO2_data.append(VO2)
self.VCO2_data.append(VCO2)
self.RQ_data.append(RQ)
self.unlock.unlock()

GUI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
class Window(QMainWindow):
def __init__(self, title):
super(Window, self).__init__()

self.title = title
palette = self.palette()
palette.setColor(self.backgroundRole(), QColor(255, 255, 255))
self.setPalette(palette)
self.setAutoFillBackground(True) # 不设置也可以
self.resize(1920, 1080)

self.flow_error = flow_error
self.environment_O2 = environment_O2
self.environment_CO2 = environment_CO2

self.O2_ser = O2_ser
self.CO2_ser = CO2_ser
self.flow_ser = flow_ser

self.setWindowTitle(self.title)
self.O2_plot, self.CO2_plot, self.flow_plot = pg.PlotWidget(), pg.PlotWidget(), pg.PlotWidget()
self.VO2_plot, self.VCO2_plot, self.RQ_plot = pg.PlotWidget(), pg.PlotWidget(), pg.PlotWidget()

self.O2_color = QColor(255, 228, 196)
self.CO2_color = QColor(255, 182, 193)
self.flow_color = QColor(135, 206, 235)
self.VO2_color = QColor(240, 255, 240)
self.VCO2_color = QColor(240, 255, 240)
self.RQ_color = QColor(255, 248, 220)

self.O2_curve = self.O2_plot.plot(
pen=pg.mkPen(color=self.O2_color, width=1)
)

self.CO2_curve = self.CO2_plot.plot(
pen=pg.mkPen(color=self.CO2_color, width=1)
)

self.flow_curve = self.flow_plot.plot(
pen=pg.mkPen(color=self.flow_color, width=1)
)

self.VO2_curve = self.VO2_plot.plot(
pen=pg.mkPen(color=self.VO2_color, width=1)
)
self.VCO2_curve = self.VCO2_plot.plot(
pen=pg.mkPen(color=self.VCO2_color, width=1)
)

self.RQ_curve = self.RQ_plot.plot(
pen=pg.mkPen(color=self.RQ_color, width=1)
)

self.init_pg_O2()
self.init_pg_CO2()
self.init_pg_flow()
self.init_pg_VO2()
self.init_pg_VCO2()
self.init_pg_RQ()

self.O2_x, self.O2_y = [], []
self.CO2_x, self.CO2_y = [], []
self.flow_x, self.flow_y = [], []

self.VO2, self.VCO2, self.RQ = [], [], []
self.calculate_x = [] # 用于 VO2、VCO2、RQ 的 x 轴显示

self.O2_mutex = QMutex()
self.CO2_mutex = QMutex()
self.flow_mutex = QMutex()
self.calculate_mutex = QMutex()

self.O2_thread = get_gas_thread(self.O2_ser, self.environment_O2, self.O2_x, self.O2_y, self.O2_mutex, self.CO2_mutex)
self.CO2_thread = get_gas_thread(self.CO2_ser, self.environment_CO2, self.CO2_x, self.CO2_y, self.CO2_mutex, self.flow_mutex)
self.flow_thread = get_flow_thread(self.flow_ser, self.flow_error, self.flow_x, self.flow_y, self.flow_mutex, self.calculate_mutex)
self.calculate_thread = calculate_thread(self.environment_O2, self.environment_CO2, self.calculate_x, self.VO2, self.VCO2, self.RQ, self.O2_y, self.CO2_y, self.flow_y,
self.calculate_mutex, self.O2_mutex)

self.CO2_mutex.lock()
self.flow_mutex.lock()
self.calculate_mutex.lock()

self.O2_thread.start()
self.CO2_thread.start()
self.flow_thread.start()
self.calculate_thread.start()

layout_vs_1 = QVBoxLayout()
layout_vs_2 = QVBoxLayout()
layout_hs_1 = QHBoxLayout()
layout_vs_3 = QVBoxLayout()

layout_vs_1.addWidget(self.O2_plot)
layout_vs_1.addWidget(self.CO2_plot)
layout_vs_1.addWidget(self.flow_plot)

layout_vs_2.addWidget(self.VO2_plot)
layout_vs_2.addWidget(self.VCO2_plot)
layout_vs_2.addWidget(self.RQ_plot)

self.label = QLabel(self)
self.label.resize(1920, 100)

self.button = QPushButton('导出数据', self)
self.button.clicked.connect(lambda: self.output_data())
self.button.resize(1920, 100)

layout_hs_1.addLayout(layout_vs_1)
layout_hs_1.addLayout(layout_vs_2)
layout_vs_3.addLayout(layout_hs_1)
layout_vs_3.addWidget(self.label)
layout_vs_3.addWidget(self.button)

self.central_widget = QWidget()
self.central_widget.setLayout(layout_vs_3)
self.setCentralWidget(self.central_widget)

# 100ms 刷新一次绘图
self.timer = QTimer()
self.timer.timeout.connect(lambda: self.plot_data())
self.timer.start(100)

def plot_data(self):
self.O2_curve.setData(self.O2_x, self.O2_y)
self.CO2_curve.setData(self.CO2_x, self.CO2_y)
self.flow_curve.setData(self.flow_x, self.flow_y)
self.VO2_curve.setData(self.calculate_x, self.VO2)
self.VCO2_curve.setData(self.calculate_x, self.VCO2)
self.RQ_curve.setData(self.calculate_x, self.RQ)
# RQ约为0.8-0.85
# 1. 運動習慣對身體能量來源消耗的影響(文献)
# 人體安靜休息時的RER約0.82、在極低強度(散步、慢跑、輕鬆騎車)運動時的RER反而下降(約0.75至0.80之間)。
# 2. https://www.adinstruments.com/
# An average human has an RER at rest of around 0.8, although this can vary a bit depending on diet and other
# factors. During a stress test, RER will typically gradually increase to a peak of about 1.2 (again variable
# depending on the individual). An RER of 1.0 is the anaerobic threshold, the point at which the body begins
# to metabolize sugar using the less efficient anaerobic pathway and build up lactic acid.
#
# 静息时VO2约为3.5ml/kg/min(1MET)
# 1. The standard oxygen consumption value equivalent to one metabolic equivalent
# (3.5 ml/min/kg) is not appropriate for elderly people
# 2. Resting Oxygen Uptake Value of 1 Metabolic Equivalent of Task in Older Adults:
# A Systematic Review and Descriptive Analysis
self.label.setText('VO2: ' + format(VO2 * 1000 / mass, '.2f') + 'mL/kg/min'
+ ' | VO2: ' + format(VO2, '.2f') + 'L/min'
+ ' | RQ: ' + format(RQ, '.2f')
+ ' | EE: ' + format(EE, '.2f') + 'kcal/min'
+ ' | Ve: ' + format(Ve, '.2f') + 'L/min')

def init_pg_O2(self):
self.O2_plot.setTitle('O2浓度 ', color=self.O2_color, size='12pt')
self.O2_plot.setLabel('left', '%')
self.O2_plot.setLabel('bottom', 'Time(s)')
self.O2_plot.setYRange(25, 14)

def init_pg_CO2(self):
self.CO2_plot.setTitle('CO2浓度 ', color=self.CO2_color, size='12pt')
self.CO2_plot.setLabel('left', '%')
self.CO2_plot.setLabel('bottom', 'Time(s)')
self.CO2_plot.setYRange(5, 0)

def init_pg_flow(self):
self.flow_plot.setTitle('通气量 ', color=self.flow_color, size='12pt')
self.flow_plot.setLabel('left', 'L/min')
self.flow_plot.setLabel('bottom', 'Time(s)')
self.flow_plot.setYRange(180, 0)

def init_pg_VO2(self):
self.VO2_plot.setTitle('摄氧量', color=self.VO2_color, size='12pt')
self.VO2_plot.setLabel('left', 'L/min')
self.VO2_plot.setLabel('bottom', 'Time(s)')
# self.VO2_plot.setYRange(60, 0)

def init_pg_VCO2(self):
self.VCO2_plot.setTitle('CO2产生速度', color=self.VCO2_color, size='12pt')
self.VCO2_plot.setLabel('left', 'L/min')
self.VCO2_plot.setLabel('bottom', 'Time(s)')
# self.VCO2_plot.setYRange(60, 0)

def init_pg_RQ(self):
self.RQ_plot.setTitle('呼吸商', color=self.RQ_color, size='12pt')
self.RQ_plot.setLabel('left', 'VCO2 / VO2')
self.RQ_plot.setLabel('bottom', 'Time(s)')
self.RQ_plot.setYRange(1.5, 0)

def output_data(self):
O2_df = pd.DataFrame({'Time': self.O2_x, 'O2': self.O2_y})
CO2_df = pd.DataFrame({'Time': self.CO2_x, 'CO2': self.CO2_y})
flow_df = pd.DataFrame({'Time': self.flow_x, 'flow': self.flow_y})

O2_df.to_csv('O2', index=False)
CO2_df.to_csv('CO2', index=False)
flow_df.to_csv('flow', index=False)


def calibration():
calibration_time_start = 0 # 计次
calibration_time_end = 30 # 校准时间
O2_calibration_data = []
CO2_calibration_data = []
flow_calibration_data = []

O2 = 20.93
CO2 = 0.03
flow = 0

def create_timer():
if calibration_time_start == calibration_time_end:
print('Calibration Complete')
print('O2: ' + str(O2) +
'| CO2: ' + str(CO2) +
'| flow error: ' + str(flow))
print('最好让系统暖机3分钟,这样不会出现延迟。至于为什么,天知道')
else:
get_data()

def get_data():
nonlocal calibration_time_start
nonlocal O2
nonlocal CO2
nonlocal flow

try:
sensor_value = O2_ser.readline().strip()
O2_value = float(sensor_value)
except Exception as e:
if calibration_time_start == 0:
O2_value = O2
else:
O2_value = O2_calibration_data[-1]
# print(e)

try:
sensor_value = CO2_ser.readline().strip()
CO2_value = float(sensor_value)
except Exception as e:
if calibration_time_start == 0:
CO2_value = CO2
else:
CO2_value = CO2_calibration_data[-1]
# print(e)

try:
sensor_value = flow_ser.readline().strip()
flow_value = float(sensor_value)
except Exception as e:
if calibration_time_start == 0:
flow_value = flow
else:
flow_value = flow_calibration_data[-1]
# print(e)

O2_calibration_data.append(O2_value)
CO2_calibration_data.append(CO2_value)
flow_calibration_data.append(flow_value)

O2 = max(O2_calibration_data, key=O2_calibration_data.count)
CO2 = max(CO2_calibration_data, key=CO2_calibration_data.count)
flow = max(flow_calibration_data, key=flow_calibration_data.count)

print('Calibrating, Wait ' + str(calibration_time_end - calibration_time_start) + ' Second')
calibration_time_start += 1
time.sleep(1)
create_timer()

print('Calibration Start...')
create_timer()

return O2, CO2, flow

Main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import sys
import time
import serial
import numpy as np
import pyqtgraph as pg
import pandas as pd
from PyQt5.QtCore import QThread, QTimer, QMutex
from PyQt5.QtWidgets import QMainWindow, QApplication, QVBoxLayout, QHBoxLayout, QWidget, QLabel, QPushButton
from PyQt5.QtGui import QColor

if __name__ == '__main__':

O2_port = '/dev/cu.usbmodem1101'
CO2_port = '/dev/cu.usbmodem1201'
flow_port = '/dev/cu.usbmodem1301'
# O2_port = '/dev/ttyACM2'
# CO2_port = '/dev/ttyACM1'
# flow_port = '/dev/ttyACM0'
baud_rate1 = 115200 # O2, flow
baud_rate2 = 9600 # CO2

RQ = 0
VO2 = 0
Ve = 0
EE = 0
mass = 67 # 体重

# 设置timeout参数,用来接收完整的数据帧
O2_ser = serial.Serial(O2_port, baud_rate1, timeout=0.1)
CO2_ser = serial.Serial(CO2_port, baud_rate2, timeout=0.1)
flow_ser = serial.Serial(flow_port, baud_rate1, timeout=0.1)

environment_O2, environment_CO2, flow_error = calibration()

app = QApplication(sys.argv)
win = Window('你猜这bug是怎么回事')
win.show()
sys.exit(app.exec_())

DataAnalysis

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np


# 过滤掉误差数据
def flow_filter(threshold, target):
df = pd.read_csv('flow')
values = []
for item in df['flow']:
value = target if abs(item) < threshold else item
values.append(value)
new_df = pd.DataFrame({'Time': df['Time'], 'flow': values})
return new_df


def O2_smooth():
def moving_average(interval, window_size):
window = np.ones(int(window_size)) / float(window_size)
return np.convolve(interval, window, 'same') # numpy的卷积函数
y_av = moving_average(df1['O2'], window_size=10)
new_df = pd.DataFrame({'Time': df1['Time'], 'O2': y_av})
return new_df


def plot_sensor_data():
fig, axes = plt.subplots(3, 1, figsize=(36, 10))

axes[0].scatter(df1['Time'], df1['O2'], c='red', marker='1', label='O2')
axes[0].scatter(df1_smooth['Time'], df1_smooth['O2'], c='lightblue', marker='.', label='O2')
axes[0].set_xlabel('time')
axes[0].set_ylabel('%')
axes[0].legend(loc=2)

axes[1].scatter(df2['Time'], df2['CO2'], c='green', marker='1', label='CO2')
axes[1].set_xlabel('time')
axes[1].set_ylabel('%')
axes[1].legend(loc=2)

axes[2].scatter(df3['Time'], df3['flow'], c='blue', marker='1', label='flow')
axes[2].set_xlabel('time')
axes[2].set_ylabel('L/min')
axes[2].legend(loc=2)


def plot_key_data():
lens = min(len(df1), len(df2), len(df3))

fi_O2 = df1['O2'][0]
fi_CO2 = df2['CO2'][0]

fi_O2 /= 100 # 20 -> 20%
fi_CO2 /= 100

VO2_y_data = []
VCO2_y_data = []

RQ0_y_data = []
RQ10_y_data = []
RQ11_y_data = []
RQ12_y_data = []
RQ13_y_data = []

x_data = []
count = 0

for i in range(lens):
fe_O2 = df1['O2'][i]
fe_CO2 = df2['CO2'][i]

fe_O2 /= 100
fe_CO2 /= 100

Ve = np.mean(df3['flow'][i:i+300])

fi_N2 = 1 - fi_O2 - fi_CO2
fe_N2 = 1 - fe_O2 - fe_CO2
Vi = Ve * fe_N2 / fi_N2
VO2 = (Vi * fi_O2) - (Ve * fe_O2)
VCO2 = (Ve * fe_CO2) - (Vi * fi_CO2)

if VO2 > 0.01 and VCO2 > 0.01:
RQ = VCO2 / VO2
else:
RQ = 0

VO2_y_data.append(VO2)
VCO2_y_data.append(VCO2)

if RQ >= 1.3:
RQ0_y_data.append(None)
RQ10_y_data.append(None)
RQ11_y_data.append(None)
RQ12_y_data.append(None)
RQ13_y_data.append(RQ)
elif 1.2 <= RQ < 1.3:
RQ0_y_data.append(None)
RQ10_y_data.append(None)
RQ11_y_data.append(None)
RQ12_y_data.append(RQ)
RQ13_y_data.append(None)
elif 1.1 <= RQ < 1.2:
RQ0_y_data.append(None)
RQ10_y_data.append(None)
RQ11_y_data.append(RQ)
RQ12_y_data.append(None)
RQ13_y_data.append(None)
elif 1.0 <= RQ < 1.1:
RQ0_y_data.append(None)
RQ10_y_data.append(RQ)
RQ11_y_data.append(None)
RQ12_y_data.append(None)
RQ13_y_data.append(None)
else:
RQ0_y_data.append(RQ)
RQ10_y_data.append(None)
RQ11_y_data.append(None)
RQ12_y_data.append(None)
RQ13_y_data.append(None)

x_data.append(count)
count += 0.1

fig, axes = plt.subplots(3, 1, figsize=(36, 10))

axes[0].scatter(x_data, VO2_y_data, c='red', marker='1', label='VO2')
axes[0].set_xlabel('time')
axes[0].set_ylabel('L/min')
axes[0].legend(loc=2)

axes[1].scatter(x_data, VCO2_y_data, c='blue', marker='1', label='VCO2')
axes[1].set_xlabel('time')
axes[1].set_ylabel('L/min')
axes[1].legend(loc=2)

axes[2].scatter(x_data, RQ0_y_data, c='lightgreen', marker='1', label='RQ<1.0')
axes[2].scatter(x_data, RQ10_y_data, c='green', marker='1', label='1.0<=RQ<1.1')
axes[2].scatter(x_data, RQ11_y_data, c='lightcoral', marker='1', label='1.1<=RQ<1.2')
axes[2].scatter(x_data, RQ12_y_data, c='red', marker='1', label='1.2<=RQ<1.3')
axes[2].scatter(x_data, RQ13_y_data, c='darkred', marker='1', label='RQ>=1.3')
axes[2].set_xlabel('time')
axes[2].set_ylabel('-')
axes[2].legend(loc=2)


# 计算一段时间内的平均通气量
def average_flow(a, b):

df = pd.read_csv('flow')
array = df['flow'][a:b]
print(np.mean(array))


df1 = pd.read_csv('O2')
df1_smooth = O2_smooth()
df2 = pd.read_csv('CO2')
df3 = flow_filter(1, 0) # 小于阈值的数据都将被赋值 0

plot_sensor_data()
plot_key_data()

average_flow(2000, 3000)

plt.show()

呼吸代谢监测:代码
https://wonderhoi.com/2023/08/29/呼吸代谢监测:代码/
作者
wonderhoi
发布于
2023年8月29日
许可协议