scipy.signal.

zpk2sos#

scipy.signal.zpk2sos(z, p, k, pairing=None, *, analog=False)[源代码]#

返回系统的零点、极点和增益的二阶节

参数:
zarray_like

传递函数的零点。

parray_like

传递函数的极点。

kfloat

系统增益。

pairing{None, ‘nearest’, ‘keep_odd’, ‘minimal’}, 可选

将零点极点对组合成节的方法。如果 analog 为 False 且 pairing 为 None,则 pairing 设置为 ‘nearest’;如果 analog 为 True,pairing 必须为 ‘minimal’,如果为 None,则会设置为 minimal。

analogbool, 可选

如果为 True,则系统为模拟系统,否则为离散系统。

在 1.8.0 版中添加。

返回:
sosndarray

二阶滤波器系数的数组,形状为 (n_sections, 6)。有关 SOS 滤波器格式规范,请参阅 sosfilt

另请参见

sosfilt

注释

用于将 ZPK 转换为 SOS 格式的算法旨在最小化因数值精度问题引起的错误。配对算法试图最小化每个双二次部分的峰值增益。这是通过将极点与最近的零配对来完成的,从单位圆最接近的极点开始(对于离散时间系统)和最接近虚轴的极点开始(对于连续时间系统)。

pairing='minimal' 输出可能不适用于 sosfiltanalog=True 输出绝不适用于 sosfilt.

算法

pairing='nearest'pairing='keep_odd'pairing='minimal' 算法中的步骤大部分是共享的。 'nearest' 算法试图最小化峰值增益,而 'keep_odd' 在奇数阶系统应将一个部分保留为一阶的限制条件下最小化峰值增益。 'minimal' 类似于 'keep_odd',但不会引入其他极点或零

算法步骤如下

对于 pairing='nearest'pairing='keep_odd' 进行预处理步骤,根据需要在原点添加极点或零以获取相同数量的极点和零以便配对。如果 pairing == 'nearest' 且极点为奇数,则在原点添加一个附加极点和一个零。

然后反复执行以下步骤,直到不再有剩余极点或零

  1. 选取最接近单位圆(或虚轴,对于 analog=True)的(下一个剩余的)极点(复数或实数),以开始新的滤波器部分。

  2. 如果极点是实数且没有其他剩余实数极点 [1],将最接近实数零添加到部分并将其保留为一阶部分。请注意,执行此步骤后,我们一定会在后续配对迭代中获得偶数个实数极点、复数极点、实数零和复数零。

  3. 其他情况

    1. 如果极点是复数,且零点是唯一剩下的实零点*,那么将极点与下一个最靠近的零点配对(保证为复数)。这样做对于确保存在一个实零点来最终创建一个一阶部分(从而保持奇数阶)是必要的。

    2. 否则,将极点与最近的剩余零点(复数或实数)配对。

    3. 通过添加另一个极点和零点到该部分中的当前极点和零点来完成二阶部分

      1. 如果当前的极点和零点都是复数,则添加它们的共轭。

      2. 否则,如果极点是复数,且零点是实数,则添加共轭极点和下一个最靠近的实零点。

      3. 否则,如果极点是实数,且零点是复数,则添加共轭零点和最靠近这些零点的实极点。

      4. 否则(我们必须有一个实极点和实零点),则添加最靠近单位圆的下一个实极点,然后添加最靠近该极点的实零点。

从 0.16.0 版本开始添加。

示例

为采样率为 8000 Hz、通带转角频率为 1000 Hz 的系统设计一个 6 阶低通椭圆数字滤波器。通带中的波纹不应超过 0.087 dB,阻带中的衰减应至少为 90 dB。

在对 ellip 的以下调用中,我们可以使用 output='sos',但对于此示例,我们将使用 output='zpk',然后使用 zpk2sos 转换为 SOS 格式。

>>> from scipy import signal
>>> import numpy as np
>>> z, p, k = signal.ellip(6, 0.087, 90, 1000/(0.5*8000), output='zpk')

现在转换为 SOS 格式。

>>> sos = signal.zpk2sos(z, p, k)

分段的分子系数

>>> sos[:, :3]
array([[0.0014152 , 0.00248677, 0.0014152 ],
       [1.        , 0.72976874, 1.        ],
       [1.        , 0.17607852, 1.        ]])

系数中的对称性出现在,因为所有零点都在单位圆上。

分段的分母系数

>>> sos[:, 3:]
array([[ 1.        , -1.32544025,  0.46989976],
       [ 1.        , -1.26118294,  0.62625924],
       [ 1.        , -1.2570723 ,  0.8619958 ]])

下一个示例显示了 pairing 选项的效果。我们有一个具有三个极点和三个零点的系统,因此 SOS 阵列将具有形状 (2, 6)。这意味着事实上在 SOS 表示中,在原点处有一个额外的极点和一个额外的零点。

>>> z1 = np.array([-1, -0.5-0.5j, -0.5+0.5j])
>>> p1 = np.array([0.75, 0.8+0.1j, 0.8-0.1j])

对于 pairing='nearest'(默认值),我们获得

>>> signal.zpk2sos(z1, p1, 1)
array([[ 1.  ,  1.  ,  0.5 ,  1.  , -0.75,  0.  ],
       [ 1.  ,  1.  ,  0.  ,  1.  , -1.6 ,  0.65]])

第一部分具有零点 {-0.5-0.05j, -0.5+0.5j} 和极点 {0, 0.75},第二部分具有零点 {-1, 0} 和极点 {0.8+0.1j, 0.8-0.1j}。请注意,原点的额外极点和零点已分配给不同的部分。

通过 pairing='keep_odd',我们得到

>>> signal.zpk2sos(z1, p1, 1, pairing='keep_odd')
array([[ 1.  ,  1.  ,  0.  ,  1.  , -0.75,  0.  ],
       [ 1.  ,  1.  ,  0.5 ,  1.  , -1.6 ,  0.65]])

根极点源点处的额外极点和零点在同一部分。第一部分实际上是第一阶部分。

通过 pairing='minimal',第一阶部分在根极点源点处没有额外极点和零点

>>> signal.zpk2sos(z1, p1, 1, pairing='minimal')
array([[ 0.  ,  1.  ,  1.  ,  0.  ,  1.  , -0.75],
       [ 1.  ,  1.  ,  0.5 ,  1.  , -1.6 ,  0.65]])