初级教程(3)创建和修改 Python 块2-带有向量的 Python 块
2.带有向量的 Python 块
本教程介绍如何修改Python 嵌入式块以接受向量输入和输出,以及向量和流之间的input_items向量索引有何不同。
上一教程创建您的第一个块演示了如何使用嵌入式 Python 块创建 Python 块。下一个教程Python Block Message Passing描述了如何使用Embedded Python Block发送和接收消息。
内容
启动流程图
本教程使用向量。请在继续之前 完成流和向量教程。
将块添加到流程图:
- 信号源
- 风门
- 流转矢量
- 嵌入式 Python 块
- 向量流
- QT GUI 时间接收器
- 虚拟水槽
- 虚拟资源
- 多变的
更改块属性:
- 信号源
- 输出类型:浮动
- 频率:100
- 多变的
- ID:矢量长度
- 价值:16
- Stream to Vector,Num Items:vectorLength
- 向量到流,Num Items:vectorLength
- 虚拟接收器,流 ID:sinusoid
- 虚拟源,流 ID:sinusoid
- QT GUI 时间接收器
- 自动缩放:是
- 输入数量:2
根据以下流程图连接块:

接受向量输入和输出
Embedded Python Block需要修改为:
- 接受矢量输入
- 产生矢量输出
- 将数据类型更改为float
关于Streams 和 Vectors教程,从更高层次的角度来看,Streams通常只是Vectors的一种特例,它只有一个并行数据元素,而不是多个数据元素。这就是为什么我们可以只更改in_sig
和out_sig
参数以使用向量而不是流。
由于流的情况很常见,它有自己的简单语法,而向量的语法稍微复杂一点。特别是,在使用向量时,我们必须指定向量的长度以及向量中元素的数据类型。我们使用 Python 中的元组来做到这一点。
双击块以编辑源代码。
将函数定义中的example_param更改为vectorSize:
def __init__(self, vectorSize=16):
更改名称:
name='最大保持块',
使用元组定义输入和输出向量信号:
in_sig=[(np.float32,vectorSize)], out_sig=[(np.float32,vectorSize)]
删除self.example_param = example_param行。
删除self.example_param的乘法:
output_items[0][:] = input_items[0]
代码现在应该如下所示:

保存代码 (CTRL + S)。将Max Hold Block连接到流程图的其余部分:

向量长度不匹配警告
嵌入式Python 块具有其他树外模块所没有的区别。在运行流程图之前,GRC 检查以确保所有连接的数据类型和向量大小匹配。这个过程中__init__()函数中vectorSize的默认值,
def __init__(self, vectorSize=16):
用于定义输入和输出向量的大小,
in_sig=[(np.float32,vectorSize)], out_sig=[(np.float32,vectorSize)]
在确定流程图是否正确时。在这种情况下vectorSize=16。GRC 假定输入和输出端口是长度为 16 的向量,即使通过块属性传入不同的参数也是如此!. 下图显示了如何将大小为 128 的矢量作为参数传入,GRC 不会将其捕获为错误,但一旦运行,流程图就会崩溃:

追溯(最近一次通话): 文件“/home/username/vectorinput.py”,第 250 行,在 <module> 中 主要的() 文件“/home/username/vectorinput.py”,第 226 行,在 main tb = top_block_cls() __init__ 中的文件“/home/username/vectorinput.py”,第 188 行 self.connect((self.blocks_stream_to_vector_0, 0), (self.epy_block_0, 0)) 文件“/usr/lib/python3/dist-packages/gnuradio/gr/hier_block2.py”,第 48 行,已包装 func(self, src, src_port, dst, dst_port) 文件“/usr/lib/python3/dist-packages/gnuradio/gr/hier_block2.py”,第 111 行,连接 self.primitive_connect(*args) 原始连接中的文件“/usr/lib/python3/dist-packages/gnuradio/gr/runtime_swig.py”,第 4531 行 返回 _runtime_swig.top_block_sptr_primitive_connect(self, *args) RuntimeError:项目大小不匹配:stream_to_vector0:0 使用 64,嵌入式 Python Block0:0 使用 512
或者,如果默认参数与其他块的矢量大小不匹配,GRC 将显示错误。在本例中,代码中默认的向量长度为 128,但传入的参数为 16:

索引流
对于流,可以使用端口号和样本索引对输入和输出进行索引。
基于端口号的索引返回特定端口的所有输入样本。例如,
输入项目[0]
返回端口 0 上的所有输入样本。
以下行返回端口 0 上的第 4 个输入样本:
输入项目[0][3]
流的索引被概括为:
input_items[portIndex][sampleIndex] output_items[portIndex][sampleIndex]
该图显示了如何可视化索引流:

索引向量
输入input_items和输出output_items在使用向量时包含一个额外的维度。
向量添加了一个额外的维度,表示为下面的vectorIndex。input_items和output_items现在是三维数组:
input_items[portIndex][vectorIndex][sampleIndex] output_items[portIndex][vectorIndex][sampleIndex]
基于portIndex的索引返回所有向量和样本的二维数组,例如:
输入项目[端口索引] output_items[端口索引]
基于portIndex和vectorIndex 的索引返回样本的一维数组,例如:
input_items[portIndex][vectorIndex] input_items[portIndex][vectorIndex]
基于portIndex、vectorIndex和sampleIndex 的索引返回单个样本。
input_items[portIndex][vectorIndex][sampleIndex] input_items[portIndex][vectorIndex][sampleIndex]
下面给出了一个视觉示例矢量索引:

创建最大保持函数
修改 work() 函数以包含最大保持函数。在input_items[0]中的所有向量上添加一个循环:
对于范围内的 vectorIndex(len(input_items[0])):
计算向量的最大值:
maxValue = np.max(input_items[0][vectorIndex])
遍历每个输入样本:
对于范围内的 sampleIndex(len(input_items[0][vectorIndex])):
分配每个输出样本maxValue:
output_items[0][vectorIndex][sampleIndex] = maxValue
代码应如下所示:

保存代码 (CTRL + S)。运行流程图。输出将显示一个正弦波和一个每 16 个样本应用最大保持的正弦波:

多向量端口
Max Hold Block被修改以添加第二个矢量输入和输出端口。
将以下块添加到工作区:
- 噪声源
- 流转矢量
- 向量流
- 虚拟水槽
- 虚拟资源
- QT GUI 时间接收器
更改以下块属性:
- 噪声源,输出类型:float
- Stream to Vector,Num Items:vectorLength
- 向量到流,Num Items:vectorLength
- Virtual Sink, Stream Id: 噪音
- 虚拟源,流 ID:噪声
- QT GUI 时间接收器
- 自动缩放:是
- 输入数量:2
连接块:

编辑Max Hold Block 的代码。添加第二个向量输入和输出:
in_sig=[(np.float32,vectorSize),(np.float32,vectorSize)], out_sig=[(np.float32,vectorSize),(np.float32,vectorSize)]

修改 work() 函数以在两个输入端口上执行最大保持 功能。
在所有输入端口上包括一个外循环:
对于范围内的 portIndex(len(input_items)):
将所有索引[0]更改为[portIndex]:
对于范围内的 portIndex(len(input_items)): 对于范围内的 vectorIndex(len(input_items[portIndex])): maxValue = np.max(input_items[portIndex][vectorIndex]) 对于范围内的 sampleIndex(len(input_items[portIndex][vectorIndex])): output_items[portIndex][vectorIndex][sampleIndex] = maxValue
代码现在应该如下所示:

保存代码并连接块:

运行流程图。现在将生成两个最大保持输出,一个用于噪声源,一个用于正弦波:

下一个教程Python Block Message Passing描述了如何使用Embedded Python Block发送和接收消息。