初级教程(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

根据以下流程图连接块:

PythonVectorStartingFlowgraph.png

接受向量输入和输出

Embedded Python Block需要修改为:

  • 接受矢量输入
  • 产生矢量输出
  • 将数据类型更改为float

关于Streams 和 Vectors教程,从更高层次的角度来看,Streams通常只是Vectors的一种特例,它只有一个并行数据元素,而不是多个数据元素。这就是为什么我们可以只更改in_sigout_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]

代码现在应该如下所示:

PythonVectorDefineBlock.png


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

PythonVectorConnectMaxHold.png

向量长度不匹配警告

嵌入式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 不会将其捕获为错误,但一旦运行,流程图就会崩溃:

MismatchVectorSizeOption1.png
追溯(最近一次通话):
  文件“/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:

MismatchVectorSizeOption2.png

索引流

对于流,可以使用端口号和样本索引对输入和输出进行索引。

基于端口号的索引返回特定端口的所有输入样本。例如,

输入项目[0]

返回端口 0 上的所有输入样本。

以下行返回端口 0 上的第 4 个输入样本:

输入项目[0][3]

流的索引被概括为:

input_items[portIndex][sampleIndex]
output_items[portIndex][sampleIndex]

该图显示了如何可视化索引流:

索引流.png

索引向量

输入input_items和输出output_items在使用向量时包含一个额外的维度。

向量添加了一个额外的维度,表示为下面的vectorIndex。input_items和output_items现在三维数组:

input_items[portIndex][vectorIndex][sampleIndex]
output_items[portIndex][vectorIndex][sampleIndex]

基于portIndex的索引返回所有向量和样本的二维数组,例如:

输入项目[端口索引]
output_items[端口索引]

基于portIndexvectorIndex 的索引返回样本的一维数组,例如:

input_items[portIndex][vectorIndex]
input_items[portIndex][vectorIndex]

基于portIndexvectorIndexsampleIndex 的索引返回单个样本。

input_items[portIndex][vectorIndex][sampleIndex]
input_items[portIndex][vectorIndex][sampleIndex]

下面给出了一个视觉示例矢量索引:

矢量索引.png

创建最大保持函数

修改 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

代码应如下所示:

MaxHoldWorkFunction.png


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

最大保持输出.png

多向量端口

Max Hold Block被修改以添加第二个矢量输入和输出端口。

将以下块添加到工作区:

  • 噪声源
  • 流转矢量
  • 向量流
  • 虚拟水槽
  • 虚拟资源
  • QT GUI 时间接收器

更改以下块属性:

  • 噪声源,输出类型:float
  • Stream to Vector,Num Items:vectorLength
  • 向量到流,Num Items:vectorLength
  • Virtual Sink, Stream Id: 噪音
  • 虚拟源,流 ID:噪声
  • QT GUI 时间接收器
    • 自动缩放:是
    • 输入数量:2

连接块:

PythonVectorNoiseSource.png


编辑Max Hold Block 的代码。添加第二个向量输入和输出:

in_sig=[(np.float32,vectorSize),(np.float32,vectorSize)],
out_sig=[(np.float32,vectorSize),(np.float32,vectorSize)]
PythonBlockSecondVector.png

修改 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

代码现在应该如下所示:

PythonVectorFinalCode.png


保存代码并连接块:

PythonVectorFinalFlowgraph.png


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

TwoMaxHoldOutputs.png


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

发表回复 0

Your email address will not be published. Required fields are marked *