PPG信号滤波过后的时频分析_ppg滤波算法-程序员宅基地

技术标签: python  信号处理  

 PPG信号的 时域图、频域图、时频图、小波变换图

 

 
import os
import time
import traceback
import pandas as pd
import plotly.plotly as py
import plotly.graph_objs as go
from plotly.offline import iplot, init_notebook_mode
import plotly
import plotly.offline as pltoff
import numpy as np
import pandas as pd

# setting offilne
plotly.offline.init_notebook_mode(connected=True)

def isNone(d):
    return (d is None or d == 'None' or
            d == '?' or
            d == '' or
            d == 'NULL' or
            d == 'null')

 

class Plotly2Html(object):
    """

    """

    def __init__(self, dataset):
        self.dataset = dataset

    def ppg_single_line_plots(self, name, title):
        # dataset = {'x': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
        #            'y': [5, 4, 1, 3, 11, 2, 6, 7, 19, 20],
        #            'z': [12, 9, 0, 0, 3, 25, 8, 17, 22, 5]}

        data_g = []

        tr_x = go.Scatter(
            x=self.dataset['x'],
            y=self.dataset['y'],
            name='PPG_G',
            mode='lines'
        )
        data_g.append(tr_x)

        # tr_z = go.Scatter(
        #     x=self.dataset['x'],
        #     y=self.dataset['z'],
        #     name='z'
        # )
        # data_g.append(tr_z)

        layout = go.Layout(title=title, xaxis={'title': 'number of ppg singnal'}, yaxis={'title': 'ppg value'},
                           font={
                               'size': 16,
                               'family': 'sans-serif'
                           }, showlegend=True,
                           legend=dict(
                               x=0.9,
                               y=1.1
                           ))
        fig = go.Figure(data=data_g, layout=layout)
        print(name)
        pltoff.plot(fig, filename=name)

    def hr_two_line_plots(self, name, title):
        # dataset = {'x': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
        #            'y': [5, 4, 1, 3, 11, 2, 6, 7, 19, 20],
        #            'z': [12, 9, 0, 0, 3, 25, 8, 17, 22, 5]}

        data_g = []
        tr_x = go.Scatter(
            x=self.dataset['x'],
            y=self.dataset['y'],
            name='Products heartRate',
            mode='lines'
        )
        data_g.append(tr_x)

        tr_z = go.Scatter(
            x=self.dataset['x'],
            y=self.dataset['z'],
            name='std heartRate',
            mode='lines'
        )
        data_g.append(tr_z)

        layout = go.Layout(title=title, xaxis={'title': 'number of samples'}, yaxis={'title': 'heartRate value'},
                           font={
                               'size': 16,
                               'family': 'sans-serif'
                           }, showlegend=True,
                           legend=dict(
                               x=0.9,
                               y=1.1
                           ))
        fig = go.Figure(data=data_g, layout=layout)
        print(name)
        pltoff.plot(fig, filename=name)

    def hr_error_value_two_line_plots(self, name, title):
        """
         方便观察不同信号质量下的心率测量的误差值
        """
        # dataset = {'x': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
        #            'y': [5, 4, 1, 3, 11, 2, 6, 7, 19, 20],
        #            'z': [12, 9, 0, 0, 3, 25, 8, 17, 22, 5]}
        data_g = []
        tr_x = go.Scatter(
            x=self.dataset['x'],
            y=self.dataset['y'],
            name='Error value',
            mode='lines'
        )
        data_g.append(tr_x)

        tr_z = go.Scatter(
            x=self.dataset['x'],
            y=self.dataset['z'],
            name='PPG Signal quality',
            mode='lines'
        )
        data_g.append(tr_z)

        layout = go.Layout(title=title, xaxis={'title': 'number of samples'},
                           yaxis={'title': 'PPG Signal quality and Error value'},
                           font={
                               'size': 16,
                               'family': 'sans-serif'
                           }, showlegend=True,
                           legend=dict(
                               x=0.9,
                               y=1.1
                           ))
        fig = go.Figure(data=data_g, layout=layout)
        print(name)
        pltoff.plot(fig, filename=name)

    # 生成柱状图
    def bar_charts(name):
        dataset = {'x': ['Windows', 'Linux', 'Unix', 'MacOS'],
                   'y1': [45, 26, 37, 13],
                   'y2': [19, 27, 33, 21]}
        data_g = []
        tr_y1 = go.Bar(
            x=dataset['x'],
            y=dataset['y1'],
            name='v1'
        )
        data_g.append(tr_y1)

        tr_y2 = go.Bar(
            x=dataset['x'],
            y=dataset['y2'],
            name='v2'
        )
        data_g.append(tr_y2)
        layout = go.Layout(title="bar charts", xaxis={'title': 'x'}, yaxis={'title': 'value'})
        fig = go.Figure(data=data_g, layout=layout)
        pltoff.plot(fig, filename=name)

    # 生成饼图
    def pie_charts(name):
        dataset = {'labels': ['Windows', 'Linux', 'Unix', 'MacOS', 'Android', 'iOS'],
                   'values': [280, 25, 10, 100, 250, 270]}
        data_g = []
        tr_p = go.Pie(
            labels=dataset['labels'],
            values=dataset['values']
        )
        data_g.append(tr_p)
        layout = go.Layout(title="pie charts")
        fig = go.Figure(data=data_g, layout=layout)
        pltoff.plot(fig, filename=name)

    # 充满区域的图
    def filled_area_plots(name):
        dataset = {'x': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
                   'y1': [5, 4, 1, 3, 11, 2, 6, 7, 19, 20],
                   'y2': [12, 9, 0, 0, 3, 25, 8, 17, 22, 5],
                   'y3': [13, 22, 46, 1, 15, 4, 18, 11, 17, 20]}

        dataset['y1_stack'] = dataset['y1']
        dataset['y2_stack'] = [y1 + y2 for y1, y2 in zip(dataset['y1'], dataset['y2'])]
        dataset['y3_stack'] = [y1 + y2 + y3 for y1, y2, y3 in zip(dataset['y1'], dataset['y2'], dataset['y3'])]

        dataset['y1_text'] = ['%s(%s%%)' % (y1, y1 * 100 / y3_s) for y1, y3_s in
                              zip(dataset['y1'], dataset['y3_stack'])]
        dataset['y2_text'] = ['%s(%s%%)' % (y2, y2 * 100 / y3_s) for y2, y3_s in
                              zip(dataset['y2'], dataset['y3_stack'])]
        dataset['y3_text'] = ['%s(%s%%)' % (y3, y3 * 100 / y3_s) for y3, y3_s in
                              zip(dataset['y3'], dataset['y3_stack'])]

        data_g = []
        tr_1 = go.Scatter(
            x=dataset['x'],
            y=dataset['y1_stack'],
            text=dataset['y1_text'],
            hoverinfo='x+text',
            mode='lines',
            name='y1',
            fill='tozeroy'
        )
        data_g.append(tr_1)

        tr_2 = go.Scatter(
            x=dataset['x'],
            y=dataset['y2_stack'],
            text=dataset['y2_text'],
            hoverinfo='x+text',
            mode='lines',
            name='y2',
            fill='tonexty'
        )
        data_g.append(tr_2)

        tr_3 = go.Scatter(
            x=dataset['x'],
            y=dataset['y3_stack'],
            text=dataset['y3_text'],
            hoverinfo='x+text',
            mode='lines',
            name='y3',
            fill='tonexty'
        )
        data_g.append(tr_3)

        layout = go.Layout(title="filled area plots", xaxis={'title': 'x'}, yaxis={'title': 'value'})
        fig = go.Figure(data=data_g, layout=layout)
        print(name)
        pltoff.plot(fig, filename=name)


def data_singnal_quality_plot(data, quality_v_start, quality_v_end):
    data_sq0 = data[(data['singnal_quality'] >= quality_v_start) & (data['singnal_quality'] <= quality_v_end)]
    ppg_list = []
    list(map(lambda x: ppg_list.extend(list(map(eval, x.strip().split(' ')))), data_sq0['ppg'].tolist()))
    return ppg_list

def plot_ppg(data):
    ppg_0_list = data_singnal_quality_plot(data, 0, 100)
    dataset = {'x': [i for i in range(len(ppg_0_list))],
               'y': ppg_0_list}
    plt2html = Plotly2Html(dataset)
    plt2html.ppg_single_line_plots("ppg_html_pig.html", "HeartRate_dayLife_24h PPG singnal")


def plot_heartRate(data):
    data = data[(data['heartrate'] > 30) & (data['std_heartrate'] > 30)]
    dataset = {'x': [i for i in range(data.shape[0])],
               'y': data['heartrate'].values,
               'z': data['std_heartrate'].values}
    plt2html = Plotly2Html(dataset)
    plt2html.hr_two_line_plots("heartRate.html", "HeartRate_dayLife_24h heartRate")


def plot_hr_error(data):
    """

    """
    data = data[(data['heartrate'] > 30) & (data['std_heartrate'] > 30)]
    data['error_value'] = data['std_heartrate'] - data['heartrate']
    dataset = {'x': [i for i in range(data.shape[0])],
               'y': data['error_value'].values,
               'z': data['singnal_quality'].values}
    plt2html = Plotly2Html(dataset)
    plt2html.hr_error_value_two_line_plots("PPG_singnal_error_value.html",
                                           "HeartRate_dayLife_24h PPG Singnal Error Value")

 

 

ppg_0_list = []
list(map(lambda x: ppg_0_list.extend(list(map(eval, x.strip().split(' ')))), dfLQ_01['ppg'].tolist()))
print("finish")

小波变换

import matplotlib.pyplot as plt 
%matplotlib inline
import pywt
cA1, cD1 = pywt.dwt(ppg_0_list, 'db3') #得到近似值和细节系数 
wap = pywt.WaveletPacket(data=ppg_0_list, wavelet='db3')
dataa = wap['a'].data
print(wap['a'].data)
print(len(wap['a'].data)) 
 
 
 
plt.figure(num='ca')
plt.plot(cA1)
plt.figure(num='cd')
plt.plot(cD1)
plt.figure(num='data')
plt.plot(dataa)
plt.show()

信号滤波

PPG最高频率220HZ,最低40HZ。

1).低通滤波

这里假设采样频率为25hz,信号本身最大的频率为220hz,要滤除220hz以上频率成分,即截至频率为220hz,则wn=2*220/25=17.6。Wn=17.6

from scipy import signal
b, a = signal.butter(8, 0.8, 'lowpass')   #配置滤波器 8 表示滤波器的阶数
b, a
(array([ 0.19287327,  1.5429862 ,  5.40045169, 10.80090339, 13.50112924,
        10.80090339,  5.40045169,  1.5429862 ,  0.19287327]),
 array([ 1.        ,  4.78451489, 10.44504107, 13.45771989, 11.12933104,
         6.0252604 ,  2.0792738 ,  0.41721716,  0.0372001 ]))
filtedData = signal.filtfilt(b, a, ppg_0_list)  #data为要过滤的信号
filtedData
array([31934.44215563, 47675.25582932, 48259.35356704, ...,
       35243.55748356, 35258.72821223, 35263.07347472])
plt.plot(filtedData)
plt.show()

高通滤波

这里假设采样频率为1000hz,信号本身最大的频率为500hz,要滤除100hz以下频率成分,即截至频率为100hz,则wn=2*100/1000=0.2。Wn=0.2

b, a = signal.butter(8, 0.16, 'highpass')   #配置滤波器 8 表示滤波器的阶数
filtedData = signal.filtfilt(b, a, ppg_0_list)  #data为要过滤的信号
plt.plot(filtedData)
plt.show()

dataset = {'x': [i for i in range(len(filtedData))],
           'y': filtedData}
plt2html = Plotly2Html(dataset)
plt2html.ppg_single_line_plots("ppg_highpass_html_pig.html", " PPG singnal highpass")

 带通滤波

这里假设采样频率为1000hz,信号本身最大的频率为500hz,要滤除100hz以下,400hz以上频率成分,即截至频率为100,400hz,则wn1=2100/1000=0.2,Wn1=0.2; wn2=2400/1000=0.8,Wn2=0.8。Wn=[0.02,0.8]

b, a = signal.butter(8, [0.16,0.9], 'bandpass')   #配置滤波器 8 表示滤波器的阶数
filtedData = signal.filtfilt(b, a, ppg_0_list)  #data为要过滤的信号
plt.plot(filtedData)
plt.show()
dataset = {'x': [i for i in range(len(filtedData))],
           'y': filtedData}
plt2html = Plotly2Html(dataset)
plt2html.ppg_single_line_plots("ppg_bandpass_html_pig.html", " PPG singnal bandpass")

带阻滤波

这里假设采样频率为1000hz,信号本身最大的频率为220hz,要滤除40hz以上,400hz以下频率成分,即截至频率为100,400hz,则wn1=2100/1000=0.2,Wn1=0.2; wn2=2400/1000=0.8,Wn2=0.8。Wn=[0.02,0.8],和带通相似,但是带通是保留中间,而带阻是去除。

b, a = signal.butter(8, [0.16,0.85], 'bandstop')   #配置滤波器 8 表示滤波器的阶数
filtedData = signal.filtfilt(b, a, ppg_0_list)  #data为要过滤的信号
plt.plot(filtedData)
plt.show()
dataset = {'x': [i for i in range(len(filtedData))],
           'y': filtedData}
plt2html = Plotly2Html(dataset)
plt2html.ppg_single_line_plots("ppg_bandstop_html_pig.html", " PPG singnal bandstop")

带通滤波后频域变换图

In [17]:

b, a = signal.butter(8, [0.16,0.9], 'bandpass')   #配置滤波器 8 表示滤波器的阶数
filtedData = signal.filtfilt(b, a, ppg_0_list)  #data为要过滤的信号
import numpy as np#导入一个数据处理模块
import pylab as pl#导入一个绘图模块,matplotlib下的模块
 
fft_size = 1024 #FFT处理的取样长度 
x = filtedData
# N点FFT进行精确频谱分析的要求是N个取样点包含整数个取样对象的波形。因此N点FFT能够完美计算频谱对取样对象的要求是n*Fs/N(n*采样频率/FFT长度),
# 因此对8KHZ和512点而言,完美采样对象的周期最小要求是8000/512=15.625HZ,所以156.25的n为10,234.375的n为15。
xs = x[:fft_size]# 从波形数据中取样fft_size个点进行运算
xf = np.fft.rfft(xs)/fft_size# 利用np.fft.rfft()进行FFT计算,rfft()是为了更方便对实数信号进行变换,由公式可知/fft_size为了正确显示波形能量
# rfft函数的返回值是N/2+1个复数,分别表示从0(Hz)到sampling_rate/2(Hz)的分。
#于是可以通过下面的np.linspace计算出返回值中每个下标对应的真正的频率:
freqs = np.linspace(0, 25, fft_size/2+1)
# np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
#在指定的间隔内返回均匀间隔的数字
xfp = 20*np.log10(np.clip(np.abs(xf), 1e-20, 1e100))
#最后我们计算每个频率分量的幅值,并通过 20*np.log10()将其转换为以db单位的值。为了防止0幅值的成分造成log10无法计算,我们调用np.clip对xf的幅值进行上下限处理

#绘图显示结果 
pl.title(u"156.25Hz and 234.375Hz WaveForm And Freq")
pl.subplot(212)
pl.plot(freqs, xfp)
pl.xlabel(u"Freq(Hz)")
pl.subplots_adjust(hspace=0.4)
pl.show()

频谱平均

对于频谱特性不随时间变化的信号,例如引擎、压缩机等机器噪声,可以对其进行长时间的采样,然后分段进行FFT计算,最后对每个频率分量的幅值求其平均值可以准确地测量信号的频谱。

def average_fft(x, fft_size):
    """
    average_fft(x, fft_size)对数组x进行fft_size点FFT运算,以dB为单位返回其平均后的幅值。由于x的长度可能不是fft_size的整数倍,
    因此首先将其缩短为fft_size的整数倍,然后用reshape函数将其转换为一个二维数组tmp。tmp的第1轴的长度为fft_size:
    """
    n = len(x) // fft_size * fft_size
    tmp = x[:n].reshape(-1, fft_size)
    tmp *= signal.hann(fft_size, sym=0)
    xf = np.abs(np.fft.rfft(tmp)/fft_size)
    avgf = np.average(xf, axis=0)
    return 20*np.log10(avgf)

xf = average_fft(x, 1000)
pl.plot(xf)
pl.show() 

短时傅里叶变换的频谱图

https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.stft.html

计算短时傅里叶变换(STFT)

scipy.signal.stft(x,fs = 1.0,window ='hann',nperseg = 256,noverlap = None,nfft = None,detrend = False,return_onesided = True,boundary ='zeros',padded = True,axis = -1 )

参数: x : array_like 时间序列的测量值

fs : float,可选 x时间序列的采样频率。默认为1.0。

window : str或tuple或array_like,可选 所需的窗口使用。如果window是一个字符串或元组,则传递给它get_window以生成窗口值,默认情况下为DFT-even。有关get_window窗口和所需参数的列表,请参阅。如果window是array_like,它将直接用作窗口,其长度必须是nperseg。默认为Hann窗口。

nperseg : int,可选 每个段的长度。默认为256。

noverlap : int,可选 段之间重叠的点数。如果没有, 。默认为无。指定时,必须满足COLA约束(请参阅下面的注释)。noverlap = nperseg // 2

nfft : int,可选 如果需要零填充FFT,则使用FFT的长度。如果为 None,则FFT长度为nperseg。默认为无。

detrend : str或function或False,可选 指定如何去除每个段的趋势。如果detrend是字符串,则将其作为类型参数传递给detrend 函数。如果它是一个函数,它需要一个段并返回一个去趋势段。如果detrend为False,则不进行去除趋势。默认为False。

return_onesided : bool,可选 如果为True,则返回实际数据的单侧频谱。如果 False返回双面光谱。请注意,对于复杂数据,始终返回双面光谱。默认为 True。

boundary : str或None,可选 指定输入信号是否在两端扩展,以及如何生成新值,以使第一个窗口段在第一个输入点上居中。这具有当所采用的窗函数从零开始时能够重建第一输入点的益处。有效选项是 。对于零填充扩展,默认为“零”。即扩展到了。['even', 'odd', 'constant', 'zeros', None][1, 2, 3, 4][0, 1, 2, 3, 4, 0]nperseg=3

填充 : bool,可选 指定输入信号在末尾是否填充零以使信号精确地拟合为整数个窗口段,以便所有信号都包含在输出中。默认为True。填充发生在边界扩展之后,如果 边界不是None,则填充为True,默认情况下也是如此。

axis : int,可选 计算STFT的轴; 默认值超过最后一个轴(即axis=-1)。

返回:

f : ndarray 采样频率数组。

t : ndarray 段时间数组。

Zxx : ndarray x的 STFT 。默认情况下,Zxx的最后一个轴对应于段时间。

import scipy.signal as signal
def stft(x, **params):
    '''
    短时傅立叶变换基本思想是将信号加滑动时间窗,并对窗内信号做傅立叶变换,得到信号的时变频谱。
    因而它的时间分辨率和频率分辨率受Heisenberg测不准原理约束,一旦窗函数选定,时频分辨率便确定下来。
    这就使它对突变信号和非平稳信号的分析存在局限性,因而不是一种动态的分析方法, 不能敏感地反映信号的突变,只适用于对缓变信号的分析。
    :param x: 输入信号
    :param params: {fs:采样频率;
                    window:窗。默认为汉明窗;
                    nperseg: 每个段的长度,默认为256,
                    noverlap:重叠的点数。指定值时需要满足COLA约束。默认是窗长的一半,
                    nfft:fft长度,
                    detrend:(str、function或False)指定如何去趋势,默认为Flase,不去趋势。
                    return_onesided:默认为True,返回单边谱。
                    boundary:默认在时间序列两端添加0
                    padded:是否对时间序列进行填充0(当长度不够的时候),
                    axis:可以不必关心这个参数}
    :return: f:采样频率数组;t:段时间数组;Zxx:STFT结果
    1.fs:表示时序信号的采样频域
    2.nperseg:表示单个时间段的长度选择,类似于时间窗的概念,对应滑窗概念里的窗长。
    3.noverlap:与前一个时间窗的相重合的时间点的长度,类似于滑窗的概念,其实就是相当于是:
     Gap = nperseg - noverlap
    4.nfft:是计算离散傅里叶变换的点数。  nfft越大,频域的分辨率就越高(分辨率=fs/nfft),但离瞬时频率就越远;noverlap影响时间轴的分辨率,越接近nfft,分辨率越高,相应的冗余就越多,计算量越大,但计算机只要能承受,问题不大。
    5.boundary:扩展参数 
    Sxx:表示最终输出的频域分析的结果,每一行代表在某一频率下所有时间窗的结果,每一列对应的是某一个时间窗下的所有频率的结果。
    f:表示输出对应的的频率。对应Sxx的每一行。
    t:表示输出对应的时间段。对应Sxx的每一列。
    '''
    f, t, zxx = signal.stft(x, **params) 
    return f, t, zxx 

import matplotlib.pyplot as plt
def stft_specgram(x, picname=None, **params):    #picname是给图像的名字,为了保存图像
    f, t, zxx = stft(x, **params) 
#     cm_light = mpl.colors.ListedColormap(['#FFA0A0','#A0FFA0',  '#A0A0FF'])
    cm_light = plt.cm.get_cmap('rainbow')
#     cm_light=plt.cm.get_cmap('flag')
#     cm_light = plt.get_cmap('PiYG')
    ct = plt.pcolormesh(t, f, np.abs(zxx), cmap=cm_light,vmin=-2,vmax=2,edgecolors='face')
    plt.colorbar(ct)
    plt.title('PPG STFT Magnitude')
    plt.ylabel('Frequency [Hz]')
    plt.xlabel('Time [sec]')
    plt.tight_layout()
    if picname is not None:
        plt.savefig('..\\picture\\' + str(picname) + '.jpg')       #保存图像
    plt.show()
#     plt.clf()      #清除画布
    pl.plot(zxx)
    pl.show() 
    return t, f, zxx 
b, a = signal.butter(10, [0.1,0.9], 'bandpass')   #配置滤波器 8 表示滤波器的阶数
filtedData = signal.filtfilt(b, a, ppg_0_list)  #data为要过滤的信号
# t, f, zxx = stft_specgram(ppg_0_list,fs=400,nperseg=500,nfft=1000,noverlap=25)
t, f, zxx = stft_specgram(filtedData,fs=440,nperseg=220, noverlap=25)

 

import seaborn as sns
fig = plt.figure(figsize=[20,6])
ax = sns.heatmap(abs(zxx),cmap="gist_earth")

 

import plotly
import plotly.offline as pltoff 
import plotly.plotly as py
import plotly.graph_objs as go
# setting offilne
plotly.offline.init_notebook_mode(connected=True)
dataset = {
    'x': [i for i in range(dfLQ_01.shape[0])],
    'y': dfLQ_01['heartrate'].values,
    'z': dfLQ_01['std_heartrate'].values
}
data_g = []
'''
['Greys', 'YlGnBu', 'Greens', 'YlOrRd', 'Bluered', 'RdBu',
'Reds', 'Blues', 'Picnic', 'Rainbow', 'Portland', 'Jet',
'Hot', 'Blackbody', 'Earth', 'Electric', 'Viridis', 'Cividis']
'''
aes1 = go.Heatmap( z=np.abs(zxx),x=t,y=f,
                 type = 'heatmap', colorscale = 'Earth')
data_g.append(aes1)

tr_x = go.Scatter(
    x= dataset['x'],
    y= dataset['y'],
    name='Products heartRate', 
    mode='lines'
)
data_g.append(tr_x)

tr_z = go.Scatter(
    x= dataset['x'],
    y= dataset['z'],
    name='std heartRate', 
    mode='lines'
)
data_g.append(tr_z) 

layout = go.Layout(
    title = 'PPG-STFT-Magnitude',
    plot_bgcolor='#ffffff',#图的背景颜色
    paper_bgcolor='#ffffff',#图像的背景颜色
    autosize = True,     
    width = 1800,
    height = 800, 
    xaxis = dict( 
        title = 'Times'
    ),
    yaxis = dict(
        title = 'Frequency'
    ),
)
fig = go.Figure(data=data_g, layout=layout)  
pltoff.plot(fig, filename="PPG-STFT-Magnitude.html")

 

import plotly
import plotly.offline as pltoff 
import plotly.plotly as py
import plotly.graph_objs as go
# setting offilne
plotly.offline.init_notebook_mode(connected=True)
data_g = []   
for item in zxx: 
    data_g.append(go.Scatter(y =np.real(item),mode = 'lines'))
    
layout = go.Layout(
    title = 'PPG-STFT-Magnitude',
    autosize = False,     
    width = 1800,
    height = 800,
#     shapes = [cross(230, 530)[0], cross(230, 530)[1], cross(230, 430)[0], cross(230, 430)[1], cross(230, 330)[0], cross(230, 330)[1], cross(300, 530)[0], cross(300, 530)[1], cross(300, 430)[0], cross(300, 430)[1], cross(370, 530)[0], cross(370, 530)[1]],
    xaxis = dict( 
        title = 'Times'
    ),
    yaxis = dict(
        title = 'Frequency'
    ),
)
fig = go.Figure(data=data_g, layout=layout)  
pltoff.plot(fig, filename="PPG-STFT-Magnitude.html")
'PPG-STFT-Magnitude.html'
fig = go.Figure(data=[go.Surface(z=np.real(zxx))])
fig.update_traces(contours_z=dict(show=True, usecolormap=True,
                                  highlightcolor="limegreen", project_z=True))
fig.layout.update(title='Mt Bruno Elevation', autosize=False,
                  scene_camera_eye=dict(x=1.87, y=0.88, z=-0.64),
                  width=1200, height=900,
                  margin=dict(l=65, r=50, b=65, t=90)
)

pltoff.plot(fig, filename="PPG-3D-STFT-Magnitude.html")

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u014033218/article/details/97369088

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签